diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 342a6c4dc8f3d0dcd2229f2a3d65bd81523605c6..760f908abd8558b580ebdfd9d8d39bcadac4d2fc 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -281,13 +281,11 @@ build-codec-instrumented-linux: # make sure that the codec builds with msan, asan and usan build-codec-sanitizers-linux: extends: - - .build-job-with-check-for-warnings + - .build-job-linux - .rules-basis script: - *print-common-info - bash ci/build_codec_sanitizers_linux.sh - # need to use the "|| exit $?" suffix to get the allowed_failure return code, otherwise the job fails with code 1...< - - ci/check_for_warnings.py $BUILD_OUTPUT || exit $? build-codec-windows-cmake: extends: diff --git a/Makefile b/Makefile index d14ddfbd1b4afd69ae2f608d70dcae08794182aa..a3cd95733473cbbbeacd5241e363690b4f551da0 100644 --- a/Makefile +++ b/Makefile @@ -67,7 +67,7 @@ LDLIBS += -lm CCCLANG = clang ifeq "$(CLANG)" "1" CC = $(CCCLANG) -CFLAGS += -fsanitize=memory +CFLAGS += -fsanitize=memory -fsanitize-memory-track-origins LDFLAGS += -fsanitize=memory endif ifeq "$(CLANG)" "2" diff --git a/Workspace_msvc/lib_com.vcxproj b/Workspace_msvc/lib_com.vcxproj index 62f0c3b2098c60bad5fea5f09d00cff6f821f154..0769491d34fd06efcaf5b6fda6b57166e5f72b86 100644 --- a/Workspace_msvc/lib_com.vcxproj +++ b/Workspace_msvc/lib_com.vcxproj @@ -254,6 +254,7 @@ + diff --git a/Workspace_msvc/lib_com.vcxproj.filters b/Workspace_msvc/lib_com.vcxproj.filters index 7b6854e7184cd0ec212f9819aa783944db688a6a..02b89d239320bfa5f5a975d62fc5bfa11c2bb2c1 100644 --- a/Workspace_msvc/lib_com.vcxproj.filters +++ b/Workspace_msvc/lib_com.vcxproj.filters @@ -466,6 +466,9 @@ common_ivas_c + + common_ivas_c + diff --git a/Workspace_msvc/lib_dec.vcxproj b/Workspace_msvc/lib_dec.vcxproj index 2851fd82e92daf535338b92b45ea87c42f9e3603..808b173a000957b098a90ec9a6e7527b136ba34c 100644 --- a/Workspace_msvc/lib_dec.vcxproj +++ b/Workspace_msvc/lib_dec.vcxproj @@ -271,7 +271,10 @@ + + + @@ -293,6 +296,7 @@ + diff --git a/Workspace_msvc/lib_dec.vcxproj.filters b/Workspace_msvc/lib_dec.vcxproj.filters index a7eb87f148c3b90ba5ca4e4fdefe4f1f60417709..ab87fd504674c00544b9323a3e29a99c61e9162a 100644 --- a/Workspace_msvc/lib_dec.vcxproj.filters +++ b/Workspace_msvc/lib_dec.vcxproj.filters @@ -16,6 +16,15 @@ dec_ivas_c + + dec_ivas_c + + + dec_ivas_c + + + dec_ivas_c + dec_ivas_c @@ -515,6 +524,9 @@ dec_ivas_c + + dec_ivas_c + diff --git a/Workspace_msvc/lib_enc.vcxproj b/Workspace_msvc/lib_enc.vcxproj index 6f88f77c4f760903c6b2a7cdbc2597ed4349c09e..e13746ea0e9953776662e1f337f5fb8c80e58a4c 100644 --- a/Workspace_msvc/lib_enc.vcxproj +++ b/Workspace_msvc/lib_enc.vcxproj @@ -215,6 +215,7 @@ + diff --git a/Workspace_msvc/lib_enc.vcxproj.filters b/Workspace_msvc/lib_enc.vcxproj.filters index b3970764c0f9218533e6f7e63c8f1d270540c0e1..c2b2c275b959eb14bb0e7239dd651ebeb5e2fe90 100644 --- a/Workspace_msvc/lib_enc.vcxproj.filters +++ b/Workspace_msvc/lib_enc.vcxproj.filters @@ -590,6 +590,9 @@ enc_ivas_c + + enc_ivas_c + diff --git a/Workspace_msvc/lib_rend.vcxproj b/Workspace_msvc/lib_rend.vcxproj index 3e5f8bee133b3600bbe891fbc67950d48db39c33..6e3943249f2e64991a5cd27b6e6a09aa25ad2f33 100644 --- a/Workspace_msvc/lib_rend.vcxproj +++ b/Workspace_msvc/lib_rend.vcxproj @@ -222,10 +222,6 @@ - - - - diff --git a/apps/decoder.c b/apps/decoder.c index 6e3e23bb4764b32f8f0bf2ea2b74251a014aa58e..fbbe04c0d30d9675526ede7e7795ed627b7a63f8 100644 --- a/apps/decoder.c +++ b/apps/decoder.c @@ -156,6 +156,12 @@ typedef struct uint16_t frontendFetchSizeMs; #endif #endif +#ifdef MASAISM_EDIT_OBJECTS + bool editing_ism_enabled; + int16_t index_of_edited_ism; + int16_t azimuth_edited_ism; + int16_t elevation_edited_ism; +#endif } DecArguments; @@ -678,6 +684,17 @@ int main( } } +#ifdef MASAISM_EDIT_OBJECTS + /*------------------------------------------------------------------------------------------* + * Set edited object positions + *------------------------------------------------------------------------------------------*/ + + if ( arg.editing_ism_enabled ) + { + IVAS_DEC_SetEditedIsmPositions( hIvasDec, arg.index_of_edited_ism, arg.azimuth_edited_ism, arg.elevation_edited_ism ); + } +#endif + /*-----------------------------------------------------------------* * Decoding *-----------------------------------------------------------------*/ @@ -894,6 +911,9 @@ static bool parseCmdlIVAS_dec( { int16_t i; char argv_to_upper[FILENAME_MAX]; +#ifdef MASAISM_EDIT_OBJECTS + int32_t tmp1; +#endif #ifdef DEBUGGING float ftmp; @@ -963,6 +983,13 @@ static bool parseCmdlIVAS_dec( #endif #endif +#ifdef MASAISM_EDIT_OBJECTS + arg->editing_ism_enabled = false; + arg->index_of_edited_ism = 0; + arg->azimuth_edited_ism = 0; + arg->elevation_edited_ism = 0; +#endif + /*-----------------------------------------------------------------* * Initialization *-----------------------------------------------------------------*/ @@ -1324,6 +1351,39 @@ static bool parseCmdlIVAS_dec( } } +#ifdef MASAISM_EDIT_OBJECTS + else if ( strcmp( argv_to_upper, "-EDIT_ISM" ) == 0 ) /* Edit ISM position: objectID, azimuth (deg), elevation (deg) */ + { + arg->editing_ism_enabled = true; + i++; + + if ( argc - i <= 6 || argv[i][0] == '-' ) + { + fprintf( stderr, "Error: Edited ISM position parameters not defined! \n\n" ); + usage_dec(); + return false; + } + + if ( sscanf( argv[i], "%d", &tmp1 ) > 0 ) + { + arg->index_of_edited_ism = (int16_t) tmp1; + i++; + } + + if ( sscanf( argv[i], "%d", &tmp1 ) > 0 ) + { + arg->azimuth_edited_ism = (int16_t) tmp1; + i++; + } + + if ( sscanf( argv[i], "%d", &tmp1 ) > 0 ) + { + arg->elevation_edited_ism = (int16_t) tmp1; + i++; + } + } +#endif + /*-----------------------------------------------------------------* * Option not recognized *-----------------------------------------------------------------*/ @@ -1682,7 +1742,11 @@ static ivas_error initOnFirstGoodFrame( } /* If outputting ISM, get number of objects, open output files and write zero metadata for initial bad frames */ +#ifdef OMASA_EXT_OUTPUT + if ( *pBsFormat == IVAS_DEC_BS_OBJ || *pBsFormat == IVAS_DEC_BS_MASA_ISM ) +#else if ( *pBsFormat == IVAS_DEC_BS_OBJ ) +#endif { if ( ( error = IVAS_DEC_GetNumObjects( hIvasDec, pNumObj ) ) != IVAS_ERR_OK ) { @@ -1720,8 +1784,13 @@ static ivas_error initOnFirstGoodFrame( } } } + /* If outputting MASA, open output file and write metadata for initial bad frames */ +#ifdef OMASA_EXT_OUTPUT + if ( *pBsFormat == IVAS_DEC_BS_MASA || *pBsFormat == IVAS_DEC_BS_MASA_ISM ) +#else else if ( *pBsFormat == IVAS_DEC_BS_MASA ) +#endif { if ( ( error = MasaFileWriter_open( arg.outputWavFilename, arg.delayCompensationEnabled, ppMasaWriter ) ) != IVAS_ERR_OK ) { @@ -1729,26 +1798,33 @@ static ivas_error initOnFirstGoodFrame( return error; } - /* Duplicate good first frame metadata to fill the beginning of stream. */ - MASA_DECODER_EXT_OUT_META_HANDLE hMasaExtOutMeta = NULL; +#ifdef OMASA_EXT_OUTPUT + if ( numInitialBadFrames > 0 ) + { +#endif + /* Duplicate good first frame metadata to fill the beginning of stream. */ + MASA_DECODER_EXT_OUT_META_HANDLE hMasaExtOutMeta = NULL; #ifdef FIX_470_MASA_JBM_EXT - if ( ( error = IVAS_DEC_GetMasaMetadata( hIvasDec, &hMasaExtOutMeta, 0 ) ) != IVAS_ERR_OK ) + if ( ( error = IVAS_DEC_GetMasaMetadata( hIvasDec, &hMasaExtOutMeta, 0 ) ) != IVAS_ERR_OK ) #else if ( ( error = IVAS_DEC_GetMasaMetadata( hIvasDec, &hMasaExtOutMeta ) ) != IVAS_ERR_OK ) #endif - { - fprintf( stderr, "\nError in IVAS_DEC_GetMasaMetadata: %s\n", IVAS_DEC_GetErrorMessage( error ) ); - return error; - } - - for ( int16_t j = 0; j < numInitialBadFrames; ++j ) - { - if ( ( error = MasaFileWriter_writeFrame( *ppMasaWriter, hMasaExtOutMeta ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "\nError writing MASA metadata to file: %s\n", MasaFileWriter_getFilePath( *ppMasaWriter ) ); + fprintf( stderr, "\nError in IVAS_DEC_GetMasaMetadata: %s\n", IVAS_DEC_GetErrorMessage( error ) ); return error; } + + for ( int16_t j = 0; j < numInitialBadFrames; ++j ) + { + if ( ( error = MasaFileWriter_writeFrame( *ppMasaWriter, hMasaExtOutMeta ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError writing MASA metadata to file: %s\n", MasaFileWriter_getFilePath( *ppMasaWriter ) ); + return error; + } + } +#ifdef OMASA_EXT_OUTPUT } +#endif } } @@ -2075,10 +2151,14 @@ static ivas_error decodeG192( #endif } - /* Write ISM metadata to external file(s) */ + /* Write MASA/ISM metadata to external file(s) */ if ( decodedGoodFrame && arg.outputFormat == IVAS_DEC_OUTPUT_EXT ) { +#ifdef OMASA_EXT_OUTPUT + if ( bsFormat == IVAS_DEC_BS_OBJ || bsFormat == IVAS_DEC_BS_MASA_ISM ) +#else if ( bsFormat == IVAS_DEC_BS_OBJ ) +#endif { if ( ( error = IVAS_DEC_GetNumObjects( hIvasDec, &numObj ) ) != IVAS_ERR_OK ) { @@ -2103,7 +2183,12 @@ static ivas_error decodeG192( } } } +#ifdef OMASA_EXT_OUTPUT + + if ( bsFormat == IVAS_DEC_BS_MASA || bsFormat == IVAS_DEC_BS_MASA_ISM ) +#else else if ( bsFormat == IVAS_DEC_BS_MASA ) +#endif { MASA_DECODER_EXT_OUT_META_HANDLE hMasaExtOutMeta; #ifdef FIX_470_MASA_JBM_EXT @@ -2190,6 +2275,16 @@ static ivas_error decodeG192( { fprintf( stdout, "\nOutput metadata file: %s\n", MasaFileWriter_getFilePath( masaWriter ) ); } +#ifdef OMASA_EXT_OUTPUT + else if ( bsFormat == IVAS_DEC_BS_MASA_ISM ) + { + for ( i = 0; i < numObj; i++ ) + { + fprintf( stdout, "\nOutput ISM metadata file: %s", IsmFileWriter_getFilePath( ismWriters[i] ) ); + } + fprintf( stdout, "\nOutput MASA metadata file: %s\n", MasaFileWriter_getFilePath( masaWriter ) ); + } +#endif } /*------------------------------------------------------------------------------------------* @@ -2656,7 +2751,11 @@ static ivas_error decodeVoIP( { int16_t i; +#ifdef OMASA_EXT_OUTPUT + if ( bsFormat == IVAS_DEC_BS_OBJ || bsFormat == IVAS_DEC_BS_MASA_ISM ) +#else if ( bsFormat == IVAS_DEC_BS_OBJ ) +#endif { if ( ( error = IVAS_DEC_GetNumObjects( hIvasDec, &numObj ) ) != IVAS_ERR_OK ) { @@ -2681,7 +2780,12 @@ static ivas_error decodeVoIP( } } } +#ifdef OMASA_EXT_OUTPUT + + if ( bsFormat == IVAS_DEC_BS_MASA || bsFormat == IVAS_DEC_BS_MASA_ISM ) +#else else if ( bsFormat == IVAS_DEC_BS_MASA ) +#endif { MASA_DECODER_EXT_OUT_META_HANDLE hMasaExtOutMeta; #ifdef FIX_470_MASA_JBM_EXT @@ -3086,7 +3190,11 @@ static ivas_error decodeVariableSpeed( /* Write ISm metadata to external file(s) */ if ( decodedGoodFrame && arg.outputFormat == IVAS_DEC_OUTPUT_EXT ) { +#ifdef OMASA_EXT_OUTPUT + if ( bsFormat == IVAS_DEC_BS_OBJ || bsFormat == IVAS_DEC_BS_MASA_ISM ) +#else if ( bsFormat == IVAS_DEC_BS_OBJ ) +#endif { if ( ( error = IVAS_DEC_GetNumObjects( hIvasDec, &numObj ) ) != IVAS_ERR_OK ) { @@ -3111,7 +3219,12 @@ static ivas_error decodeVariableSpeed( } } } +#ifdef OMASA_EXT_OUTPUT + + if ( bsFormat == IVAS_DEC_BS_MASA || bsFormat == IVAS_DEC_BS_MASA_ISM ) +#else else if ( bsFormat == IVAS_DEC_BS_MASA ) +#endif { MASA_DECODER_EXT_OUT_META_HANDLE hMasaExtOutMeta; #ifdef FIX_470_MASA_JBM_EXT @@ -3265,7 +3378,11 @@ static ivas_error decodeVariableSpeed( /* Write ISm metadata to external file(s) */ if ( decodedGoodFrame && arg.outputFormat == IVAS_DEC_OUTPUT_EXT ) { +#ifdef OMASA_EXT_OUTPUT + if ( bsFormat == IVAS_DEC_BS_OBJ || bsFormat == IVAS_DEC_BS_MASA_ISM ) +#else if ( bsFormat == IVAS_DEC_BS_OBJ ) +#endif { if ( ( error = IVAS_DEC_GetNumObjects( hIvasDec, &numObj ) ) != IVAS_ERR_OK ) { @@ -3290,7 +3407,12 @@ static ivas_error decodeVariableSpeed( } } } +#ifdef OMASA_EXT_OUTPUT + + if ( bsFormat == IVAS_DEC_BS_MASA || bsFormat == IVAS_DEC_BS_MASA_ISM ) +#else else if ( bsFormat == IVAS_DEC_BS_MASA ) +#endif { MASA_DECODER_EXT_OUT_META_HANDLE hMasaExtOutMeta; #ifdef FIX_470_MASA_JBM_EXT @@ -3354,6 +3476,16 @@ static ivas_error decodeVariableSpeed( { fprintf( stdout, "\nOutput metadata file: %s\n", MasaFileWriter_getFilePath( masaWriter ) ); } +#ifdef OMASA_EXT_OUTPUT + else if ( bsFormat == IVAS_DEC_BS_MASA_ISM ) + { + for ( i = 0; i < numObj; i++ ) + { + fprintf( stdout, "\nOutput ISM metadata file: %s", IsmFileWriter_getFilePath( ismWriters[i] ) ); + } + fprintf( stdout, "\nOutput MASA metadata file: %s\n", MasaFileWriter_getFilePath( masaWriter ) ); + } +#endif } /* add zeros at the end to have equal length of synthesized signals */ diff --git a/apps/encoder.c b/apps/encoder.c index 75798f240d0545b66151f788de31cf1a9442c88a..4ff90a8d39e394c5ff3cfc55327ed771c1d87c7c 100644 --- a/apps/encoder.c +++ b/apps/encoder.c @@ -89,6 +89,15 @@ typedef union _EncInputFormatConfig /* MC details */ IVAS_ENC_MC_LAYOUT mcLayout; +#ifdef MASA_AND_OBJECTS + struct EncMasaIsmConfig + { + int16_t numObjects; + const char *metadataFiles[IVAS_MAX_NUM_OBJECTS]; + IVAS_ENC_MASA_VARIANT masaVariant; + } masa_ism; +#endif + } EncInputFormatConfig; /* Struct for storing cmdln arguments */ @@ -427,6 +436,15 @@ int main( goto cleanup; } break; +#ifdef MASA_AND_OBJECTS + case IVAS_ENC_INPUT_MASA_ISM: + if ( ( error = IVAS_ENC_ConfigureForMASAObjects( hIvasEnc, arg.inputFs, totalBitrate, bandwidth, arg.dtxConfig, arg.inputFormatConfig.masa_ism.numObjects, arg.inputFormatConfig.masa_ism.masaVariant ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nIVAS_ENC_ConfigureForMASAObjects failed: %s\n\n", IVAS_ENC_GetErrorMessage( error ) ); + exit( -1 ); + } + break; +#endif default: fprintf( stderr, "\nInvalid input type\n\n" ); goto cleanup; @@ -511,7 +529,11 @@ int main( } } +#ifdef MASA_AND_OBJECTS + const int16_t numIsmInputs = ( arg.inputFormat == IVAS_ENC_INPUT_ISM || arg.inputFormat == IVAS_ENC_INPUT_MASA_ISM ) ? arg.inputFormatConfig.ism.numObjects : 0; +#else const int16_t numIsmInputs = arg.inputFormat == IVAS_ENC_INPUT_ISM ? arg.inputFormatConfig.ism.numObjects : 0; +#endif for ( i = 0; i < numIsmInputs; ++i ) { @@ -1490,6 +1512,100 @@ static bool parseCmdlIVAS_enc( return false; } } +#ifdef MASA_AND_OBJECTS + else if ( strcmp( to_upper( argv[i] ), "-ISM_MASA" ) == 0 ) + { + arg->inputFormat = IVAS_ENC_INPUT_MASA_ISM; + i++; + + if ( i < argc - 5 ) + { + if ( sscanf( argv[i], "%d", &tmp ) > 0 ) + { + i++; + } + + if ( tmp <= 0 ) + { + fprintf( stderr, "Error: Too low number of ISM channels specified!\n\n" ); + usage_enc(); + } + else + { + if ( tmp <= IVAS_MAX_NUM_OBJECTS ) /* number of ISM channels */ + { + arg->inputFormatConfig.masa_ism.numObjects = (int16_t) tmp; + } + else + { + fprintf( stderr, "Error: Too high number of ISM channels!\n\n" ); + usage_enc(); + } + } + } + else + { + fprintf( stderr, "Error: Number of ISM channels not specified!\n\n" ); + usage_enc(); + } + if ( i < argc - 4 ) + { + if ( sscanf( argv[i], "%d", &tmp ) > 0 ) + { + i++; + } + + switch ( tmp ) + { + case 1: + arg->inputFormatConfig.masa_ism.masaVariant = IVAS_ENC_MASA_1CH; + break; + case 2: + arg->inputFormatConfig.masa_ism.masaVariant = IVAS_ENC_MASA_2CH; + break; + default: + fprintf( stderr, "Error: MASA channels must for the moment be 1 or 2.\n\n" ); + usage_enc(); + break; + } + } + + /* read input metadata files */ + for ( j = 0; j < arg->inputFormatConfig.masa_ism.numObjects; j++ ) + { + if ( i < argc - 4 ) + { + if ( strcmp( argv[i], "NULL" ) == 0 || strcmp( argv[i], "null" ) == 0 ) + { + /* no metadata input file -> encode only audio streams */ + arg->inputFormatConfig.masa_ism.metadataFiles[j] = NULL; + } + else + { + arg->inputFormatConfig.masa_ism.metadataFiles[j] = argv[i]; + } + + i++; + } + else + { + fprintf( stderr, "Error: not enough arguments\n\n" ); + usage_enc(); + } + } + + if ( i < argc - 4 ) + { + arg->masaMetadataFile = argv[i]; + i++; + } + else + { + fprintf( stderr, "Error: not enough MASA arguments\n\n" ); + usage_enc(); + } + } +#endif else if ( strcmp( argv_to_upper, "-STEREO_DMX_EVS" ) == 0 ) { arg->inputFormat = IVAS_ENC_INPUT_MONO; @@ -1671,6 +1787,10 @@ static void usage_enc( void ) fprintf( stdout, " for 4 ISM also 512000 \n" ); fprintf( stdout, " for IVAS SBA, MASA, MC R=(13200, 16400, 24400, 32000, 48000, 64000, 80000, \n" ); fprintf( stdout, " 96000, 128000, 160000, 192000, 256000, 384000, 512000) \n" ); +#ifdef MASA_AND_OBJECTS + fprintf( stdout, " for IVAS objects-MASA R =(13200, 16400, 24400, 32000, 48000, 64000, 96000, 128000, \n" ); + fprintf( stdout, " 160000, 192000, 256000, 384000, 512000)\n" ); +#endif fprintf( stdout, " Alternatively, R can be a bitrate switching file which consists of R values\n" ); fprintf( stdout, " indicating the bitrate for each frame in bps. These values are stored in\n" ); fprintf( stdout, " binary format using 4 bytes per value\n" ); @@ -1694,6 +1814,13 @@ static void usage_enc( void ) fprintf( stdout, "-masa Ch File : MASA format \n" ); fprintf( stdout, " where Ch specifies the number of input/transport channels (1 or 2): \n" ); fprintf( stdout, " and File specifies input file containing parametric MASA metadata \n" ); +#ifdef MASA_AND_OBJECTS + fprintf( stdout, "-ism_masa IsmChannels MasaChannels IsmFiles MasaFile : MASA and objects format \n" ); + fprintf( stdout, " where IsmChannels specifies the number of ISms (1-4)\n" ); + fprintf( stdout, " and MasaChannels specifies the number of MASA input/transport channels (1 or 2) \n" ); + fprintf( stdout, " and IsmFiles specify input files containing metadata, one file per object \n" ); + fprintf( stdout, " and MasaFile specifies MASA input file containing parametric metadata \n" ); +#endif fprintf( stdout, "-mc InputConf : Multi-channel format\n" ); fprintf( stdout, " where InputConf specifies the channel configuration: 5_1, 7_1, 5_1_2, 5_1_4, 7_1_4\n" ); fprintf( stdout, " Loudspeaker positions are assumed to have azimuth and elevation as per \n" ); diff --git a/ci/build_codec_sanitizers_linux.sh b/ci/build_codec_sanitizers_linux.sh index 4e40f89b9a028d89363c97ec2fbab109474334b8..d352fa32ec1cd6d8d3283c4984ba428c117b5769 100755 --- a/ci/build_codec_sanitizers_linux.sh +++ b/ci/build_codec_sanitizers_linux.sh @@ -40,5 +40,4 @@ make CLANG=1 -j make clean make CLANG=2 -j make clean -# write out one build for warnings check -make CLANG=3 -j 2>&1 | tee build_output.txt +make CLANG=3 -j diff --git a/lib_com/bitstream.c b/lib_com/bitstream.c index 3fe32b04e3f36efd20836eb59ad6b314e810d247..fb27e89e00cc65a63de236f563cadf82bd2900ff 100644 --- a/lib_com/bitstream.c +++ b/lib_com/bitstream.c @@ -532,6 +532,51 @@ int16_t get_ivas_max_num_indices( return 1650; } } +#ifdef MASA_AND_OBJECTS + else if ( ivas_format == MASA_ISM_FORMAT ) + { + if ( ivas_total_brate <= IVAS_16k4 ) + { + return 300; + } + else if ( ivas_total_brate <= IVAS_32k ) + { + return 400; + } + else if ( ivas_total_brate <= IVAS_48k ) + { + return 650; + } + else if ( ivas_total_brate <= IVAS_80k ) + { + return 750; + } + else if ( ivas_total_brate <= IVAS_160k ) + { + return 850; + } + else if ( ivas_total_brate <= IVAS_192k ) + { + return 950; + } + else if ( ivas_total_brate <= IVAS_256k ) + { +#ifdef OMASA_BIT_BUFF_SZ + return 1300; +#else + return 1150; +#endif + } + else if ( ivas_total_brate <= IVAS_384k ) + { + return 1450; + } + else + { + return 1650; + } + } +#endif else if ( ivas_format == MC_FORMAT ) { if ( ivas_total_brate <= IVAS_16k4 ) @@ -900,6 +945,51 @@ int16_t get_ivas_max_num_indices_metadata( return 1750; } } +#ifdef MASA_AND_OBJECTS + else if ( ivas_format == MASA_ISM_FORMAT ) + { + if ( ivas_total_brate <= IVAS_16k4 ) + { + return 80; + } + else if ( ivas_total_brate <= IVAS_32k ) + { + return 125 + 100; + } + else if ( ivas_total_brate <= IVAS_48k ) + { + return 205 + 100; + } + else if ( ivas_total_brate <= IVAS_96k ) + { + return 240 + 150; + } + else if ( ivas_total_brate <= IVAS_128k ) + { + return 305 + 30; + } + else if ( ivas_total_brate <= IVAS_160k ) + { + return 425 + 30; + } + else if ( ivas_total_brate <= IVAS_192k ) + { + return 630 + 30; + } + else if ( ivas_total_brate <= IVAS_256k ) + { + return 850 + 30; + } + else if ( ivas_total_brate <= IVAS_384k ) + { + return 1000 + 30; + } + else + { + return 1750 + 30; + } + } +#endif else if ( ivas_format == MC_FORMAT ) { if ( ivas_total_brate <= IVAS_13k2 ) @@ -2715,6 +2805,25 @@ ivas_error preview_indices( break; case 2: st_ivas->ivas_format = ISM_FORMAT; + + if ( total_brate >= IVAS_24k4 ) + { + if ( bit_stream[2] ) + { +#ifdef MASA_AND_OBJECTS + if ( bit_stream[3] ) + { + /* Placeholder for SBA + objects */ + } + else + { + st_ivas->ivas_format = MASA_ISM_FORMAT; + } +#else + /* placeholder for combined format signaling */ +#endif + } + } break; case 3: if ( bit_stream[2] == 0 ) @@ -2877,6 +2986,20 @@ ivas_error preview_indices( ivas_sba_config( total_brate, st_ivas->sba_analysis_order, -1, &( st_ivas->nchan_transport ), st_ivas->sba_planar, &( st_ivas->nSCE ), &( st_ivas->nCPE ), &( st_ivas->element_mode_init ) ); } +#ifdef MASA_AND_OBJECTS + else if ( st_ivas->ivas_format == MASA_ISM_FORMAT ) + { + /* read number of objects from the bitstream */ + st_ivas->nchan_transport = 2; /* always 2 MASA transport channels */ + st_ivas->nchan_ism = 0; + + if ( total_brate != SID_2k40 && total_brate != FRAME_NO_DATA ) + { + st_ivas->nchan_ism = 2 * bit_stream[total_brate / FRAMES_PER_SEC - 1] + bit_stream[total_brate / FRAMES_PER_SEC - 2] + 1; + st_ivas->ism_mode = ivas_omasa_ism_mode_select( total_brate, st_ivas->nchan_ism ); + } + } +#endif } st_ivas->hDecoderConfig->ivas_total_brate = total_brate; diff --git a/lib_com/cnst.h b/lib_com/cnst.h index b6e033b7c54926f9123f6ea40a5831aa5150c7e2..a66938354e7046307039c8cbcc34eaad13853e39 100644 --- a/lib_com/cnst.h +++ b/lib_com/cnst.h @@ -263,6 +263,9 @@ enum{ enum { IND_IVAS_FORMAT, +#ifdef MASA_AND_OBJECTS + IND_SMODE_OMASA, +#endif IND_SMODE, IND_SID_TYPE, IND_BWIDTH, diff --git a/lib_com/delay_comp.c b/lib_com/delay_comp.c index 7d2d5deb5298ff04b5a77d058f93aa436d7e78ea..74ae97311e6aafde538db09657d4ce976870f4b5 100644 --- a/lib_com/delay_comp.c +++ b/lib_com/delay_comp.c @@ -73,7 +73,11 @@ int32_t get_delay( { delay = IVAS_ENC_DELAY_NS; +#ifdef MASA_AND_OBJECTS + if ( ivas_format == MASA_FORMAT || ivas_format == MASA_ISM_FORMAT ) +#else if ( ivas_format == MASA_FORMAT ) +#endif { delay = 0; /* All delay is compensated in the decoder with MASA */ } @@ -115,7 +119,11 @@ int32_t get_delay( } #endif +#ifdef MASA_AND_OBJECTS + if ( ivas_format == MASA_FORMAT || ivas_format == MASA_ISM_FORMAT ) +#else if ( ivas_format == MASA_FORMAT ) +#endif { delay += IVAS_ENC_DELAY_NS; /* Compensate also the encoder delay in the decoder with MASA */ } diff --git a/lib_com/ivas_cnst.h b/lib_com/ivas_cnst.h index 4cd06c6ed45e1bdf67dcc36a717ca47b599211c4..f4db6dd47b1ef98e26c46d935f0e884049c0c101 100644 --- a/lib_com/ivas_cnst.h +++ b/lib_com/ivas_cnst.h @@ -69,7 +69,9 @@ typedef enum SBA_FORMAT, /* IVAS SBA (ambisonics) format */ MASA_FORMAT, /* IVAS MASA format */ MC_FORMAT, /* IVAS multi-channel format */ - +#ifdef MASA_AND_OBJECTS + MASA_ISM_FORMAT, /* IVAS combined MASA + objects format*/ +#endif } IVAS_FORMAT; @@ -79,6 +81,9 @@ typedef enum #define IVAS_FORMAT_SIGNALING_NBITS 2 /* number of bits for signaling the IVAS format */ #define IVAS_FORMAT_SIGNALING_NBITS_EXTENDED ( IVAS_FORMAT_SIGNALING_NBITS + 1 ) +#ifdef MASA_AND_OBJECTS +#define IVAS_COMBINED_FORMAT_SIGNALLING_BITS 1 +#endif /*----------------------------------------------------------------------------------* @@ -208,7 +213,7 @@ typedef enum #define MAX_JBM_SUBFRAMES_5MS 8 #define DEFAULT_JBM_SUBFRAMES_5MS 4 #define JBM_CLDFB_SLOTS_IN_SUBFRAME 4 -#define MAX_JBM_CLDFB_TIMESLOTS 32 +#define MAX_JBM_CLDFB_TIMESLOTS 32 #define DEFAULT_JBM_CLDFB_TIMESLOTS 16 #define MAX_JBM_L_FRAME48k 1920 #define MAX_JBM_L_FRAME_NS 40000000L @@ -313,7 +318,13 @@ typedef enum #define MIN_BRATE_SWB_SCE ACELP_9k60 /* min. SCE bitrate where SWB is supported */ #define MIN_BRATE_SWB_STEREO IVAS_13k2 /* min. stereo bitrate where SWB is supported */ #define MIN_BRATE_FB_STEREO IVAS_32k /* min. SCE and stereo bitrate where FB is supported */ +#ifdef ISM_FB +#ifdef ISM_FB_16k4 #define MIN_BRATE_FB_ISM 16000 /* min. SCE bitrate where FB is supported in ISM format */ +#else +#define MIN_BRATE_FB_ISM 24000 /* min. SCE bitrate where FB is supported in ISM format */ +#endif +#endif #define MIN_TDM_BRATE_WB_TBE_1k05 12000 /* min. per channel bitrate where WB TBE @1.05 kbps is supported (0.35kbs at lower bitrates) */ #define MIN_BRATE_WB_TBE_1k05 9650 /* min. per channel bitrate where WB TBE @1.05 kbps is supported (0.35kbs at lower bitrates) */ @@ -337,11 +348,23 @@ typedef enum #define ISM_METADATA_INACTIVE_FLAG_BITS 1 /* flag to signal whether MD are sent in low-rate inactive frame */ #define ISM_METADATA_FLAG_BITS 2 +#ifdef MASA_AND_OBJECTS +#define ISM_INACTIVE_IMP 0 /* == ISM_NO_META */ +#endif #define ISM_NO_META 0 #define ISM_LOW_IMP 1 #define ISM_MEDIUM_IMP 2 #define ISM_HIGH_IMP 3 +#ifdef MASA_AND_OBJECTS +#define BRATE_ISM_INACTIVE 2450 /* CoreCoder bitrate in ISM no meta / inactive frames */ +#define BITS_ISM_INACTIVE ( BRATE_ISM_INACTIVE / FRAMES_PER_SEC ) +#ifdef MASA_AND_OBJECTS +#define ADJUST_ISM_BRATE_NEG 6000 +#define ADJUST_ISM_BRATE_POS 8000 +#endif +#endif + #define ISM_AZIMUTH_NBITS 7 #define ISM_AZIMUTH_MIN -180.0f #define ISM_AZIMUTH_MAX 180.0f @@ -395,6 +418,13 @@ typedef enum ISM_MODE_NONE, ISM_MODE_DISC, /* discrete ISM */ ISM_MODE_PARAM /* parametric ISM */ +#ifdef MASA_AND_OBJECTS + , + ISM_MASA_MODE_MASA_ONE_OBJ, /* MASA ISM mode when one object is encoded separately and remainder using MASA parameters */ + ISM_MASA_MODE_PARAM_ONE_OBJ, /* MASA ISM mode when one object is encoded separately and remainder using parametric object model */ + ISM_MASA_MODE_DISC /* MASA ISM mode when all objects are encoded separarately */ +#endif + } ISM_MODE; @@ -403,7 +433,7 @@ enum { IND_ISM_NUM_OBJECTS, IND_ISM_EXTENDED_FLAG = IND_ISM_NUM_OBJECTS + MAX_NUM_OBJECTS, - IND_ISM_EXTENDED_NDP_FLAG, + IND_ISM_EXTENDED_NDP_FLAG, IND_ISM_METADATA_FLAG, IND_ISM_MD_NULL_FLAG = IND_ISM_METADATA_FLAG + MAX_NUM_OBJECTS, IND_ISM_MD_INACTIVE_FLAG = IND_ISM_MD_NULL_FLAG + MAX_NUM_OBJECTS, @@ -655,7 +685,7 @@ enum IND_STEREO_DFT_SIDEGAIN_FLAG, IND_STEREO_DFT_SIDEGAINS, - IND_STEREO_DFT_ITD_MODE = IND_STEREO_DFT_SIDEGAINS + 4 * STEREO_DFT_BAND_MAX + 72, + IND_STEREO_DFT_ITD_MODE = IND_STEREO_DFT_SIDEGAINS + 4 * STEREO_DFT_BAND_MAX + 120, IND_STEREO_DFT_ITD_HUFF, IND_STEREO_DFT_ITD_NEG, @@ -1173,6 +1203,12 @@ enum #define MASA_DELTA_AZI_DCT 10 #define MASA_TRANSP_BITS 1 +#ifdef MASA_AND_OBJECTS +#define NO_BITS_MASA_ISM_NO_OBJ 2 +#define MASA2TOTAL_THR 0.98f +#define BITS_MASA2TOTTAL_DCT0 6 +#define STEP_M2T 0.1f +#endif #define MASA_HEADER_BITS 2 #define MASA_SUBFRAME_BITS 1 #define MASA_LOWBITRATE_MODE_BITS 1 @@ -1236,6 +1272,13 @@ enum #define MASA_ANGLE_AT_EQUATOR_DEG 0.738796268264740f #define MASA_INV_ANGLE_AT_EQUATOR_DEG 1.353553128183453f #define MASA_STEREO_MIN_BITRATE IVAS_24k4 +#ifdef MASA_AND_OBJECTS +#define MAXIMUM_OMASA_FREQ_BANDS 8 /* Corresponds to maximum number of coding bands at 32 kbps */ +#ifdef MASA_AND_OBJECTS +#define OMASA_STEREO_SW_CNT_MAX 100 +#define OMASA_STEREO_SW_CNT_MAX2 5 +#endif +#endif #define MASA_BIT_REDUCT_PARAM 10 #define MASA_MAXIMUM_TWO_DIR_BANDS 24 @@ -1426,8 +1469,12 @@ typedef enum #define PARAM_MC_MAX_BAND_ABS_COV_DEC 10 #define PARAM_MC_ENER_LIMIT_INTRAFRAME (1.5f) #define PARAM_MC_ENER_LIMIT_INTERFRAME (2.0f) +#ifdef FIX_563_PARAMMC_LIMITER #define PARAM_MC_ENER_LIMIT_MAX_DELTA_FAC (15.0f) +#endif +#ifdef FIX_580_PARAMMC_ENER_BURSTS #define PARAM_MC_NUM_ATTACK_ILD_THRESH (3) +#endif #define PARAM_MC_LFE_ON_THRESH (8000.0f) #define PARAM_MC_BAND_TO_MDCT_BAND_RATIO 16 /* Ratio of resolution of CLDFB Bands to MDCT Bands */ #define PARAM_MC_SLOT_ENC_NS 2500000L diff --git a/lib_com/ivas_ism_com.c b/lib_com/ivas_ism_com.c index 7944311470c85fc0c79707a2aa804764d9d2ddd0..1c25269f6b82703629e5d1aafa106e00407469e9 100644 --- a/lib_com/ivas_ism_com.c +++ b/lib_com/ivas_ism_com.c @@ -54,7 +54,9 @@ #define BETA_ISM_LOW_IMP 0.6f #define BETA_ISM_MEDIUM_IMP 0.8f +#ifdef FIX_562_ISM2_64KBPS #define MAX_BRATE_TCX_32k 48000 +#endif /*-------------------------------------------------------------------* @@ -63,7 +65,11 @@ * Convert bit-budget to bitrate *-------------------------------------------------------------------*/ +#ifdef MASA_AND_OBJECTS +void bitbudget_to_brate( +#else static void bitbudget_to_brate( +#endif const int16_t x[], /* i : bitbudgets */ int32_t y[], /* o : bitrates */ const int16_t N /* i : number of entries to be converted */ @@ -97,6 +103,10 @@ ivas_error ivas_ism_config( int32_t element_brate[], /* o : element bitrate per object */ int32_t total_brate[], /* o : total bitrate per object */ int16_t nb_bits_metadata[] /* i/o: number of metadata bits */ +#ifdef MASA_AND_OBJECTS + , + const int16_t combined_format_flag /* i : flag indicating combined format */ +#endif ) { int16_t ch; @@ -109,8 +119,18 @@ ivas_error ivas_ism_config( ivas_error error; error = IVAS_ERR_OK; - - n_ISms = nchan_transport; +#ifdef MASA_AND_OBJECTS + if ( combined_format_flag ) + { + n_ISms = nchan_ism; + } + else + { +#endif + n_ISms = nchan_transport; +#ifdef MASA_AND_OBJECTS + } +#endif /* initialization */ ism_metadata_flag_global = 0; @@ -123,6 +143,59 @@ ivas_error ivas_ism_config( } } +#ifdef MASA_AND_OBJECTS + /* decision about bitrates per channel */ + if ( combined_format_flag ) + { + /* combined format: decision about bitrates per channel - variable during the session (at one ivas_total_brate) */ + bits_ism = (int16_t) ( ism_total_brate / FRAMES_PER_SEC ); + set_s( bits_element, bits_ism / n_ISms, n_ISms ); + bits_element[n_ISms - 1] += bits_ism % n_ISms; + + /* ISM common signaling bits are counted in MASA MD bit-budget */ + } + else + { + /* ISM format: decision about bitrates per channel - constant during the session (at one ivas_total_brate) */ + bits_ism = (int16_t) ( ism_total_brate / FRAMES_PER_SEC ); + set_s( bits_element, bits_ism / n_ISms, n_ISms ); + bits_element[n_ISms - 1] += bits_ism % n_ISms; + bitbudget_to_brate( bits_element, element_brate, n_ISms ); + + /* count ISm common signaling bits */ + if ( hIsmMeta != NULL ) + { + nb_bits_metadata[0] += n_ISms * ISM_METADATA_FLAG_BITS + nchan_ism; + + if ( ism_total_brate >= ISM_EXTENDED_METADATA_BRATE ) + { + nb_bits_metadata[0] += ISM_EXTENDED_METADATA_BITS; + + if ( ism_extended_metadata_flag ) + { + nb_bits_metadata[0] += ISM_METADATA_IS_NDP_BITS; + } + } + + for ( ch = 0; ch < n_ISms; ch++ ) + { + if ( null_metadata_flag[ch] ) + { + nb_bits_metadata[0] += ISM_METADATA_MD_FLAG_BITS; + nb_bits_metadata[0] += ISM_METADATA_FLAG_BITS; + } + else + { + if ( ism_imp[ch] == ISM_NO_META ) + { + nb_bits_metadata[0] += ISM_METADATA_MD_FLAG_BITS; + nb_bits_metadata[0] += ISM_METADATA_INACTIVE_FLAG_BITS; + } + } + } + } + } +#else /* decision about bitrates per channel - constant during the session (at one ivas_total_brate) */ bits_ism = (int16_t) ( ism_total_brate / FRAMES_PER_SEC ); set_s( bits_element, bits_ism / n_ISms, n_ISms ); @@ -160,6 +233,7 @@ ivas_error ivas_ism_config( } } } +#endif /* split metadata bitbudget equally between channels */ if ( nb_bits_metadata != NULL ) @@ -290,7 +364,8 @@ ivas_error ivas_ism_config( bits_CoreCoder[ch] = tmp; } - /* limitaton to avoid too high bitrate in one active TCX channel */ +#ifdef FIX_562_ISM2_64KBPS + /* limitation to avoid too high bitrate in one active TCX channel */ if ( element_brate[0] >= SCE_CORE_16k_LOW_LIMIT && element_brate[0] <= IVAS_32k ) { diff = 0; @@ -304,6 +379,7 @@ ivas_error ivas_ism_config( bits_CoreCoder[ch] = tmp; } } +#endif if ( diff > 0 ) { @@ -326,12 +402,44 @@ ivas_error ivas_ism_config( printf( "\nWarning: ISM bitbudget equal to SID!\n" ); } #endif + +#ifdef MASA_AND_OBJECTS + if ( combined_format_flag ) + { + diff = 0; + } +#endif break; } } } } +#ifdef MASA_AND_OBJECTS + if ( combined_format_flag ) + { + if ( diff > 0 ) + { + for ( ch = 0; ch < n_ISms; ch++ ) + { + if ( ism_imp[ch] <= ISM_MEDIUM_IMP ) + { + if ( diff > limit_high ) + { + diff += bits_CoreCoder[ch] - limit_high; + bits_CoreCoder[ch] = limit_high; + } + else + { + bits_CoreCoder[ch] += diff; + break; + } + } + } + } + } +#endif + bitbudget_to_brate( bits_CoreCoder, total_brate, n_ISms ); } @@ -340,7 +448,11 @@ ivas_error ivas_ism_config( { int32_t tmpL; tmpL = sum_l( total_brate, n_ISms ) + bits_side * FRAMES_PER_SEC; +#ifdef MASA_AND_OBJECTS + if ( ism_total_brate != tmpL ) +#else if ( sum_l( element_brate, n_ISms ) != tmpL ) +#endif { return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "\nError: Mismatch in ISM bit-budget distribution. Exiting!\n" ); } @@ -506,8 +618,10 @@ void ivas_param_ism_config( hParamIsm->last_el_sgn[i] = 1; } +#ifdef FIX_549_DMX_GAIN hParamIsm->last_dmx_gain = 1.0f; set_f( hParamIsm->last_cardioid_left, 1.0f, MAX_NUM_OBJECTS ); +#endif return; } @@ -546,7 +660,11 @@ ISM_MODE ivas_ism_mode_select( * ---------------------------------------------------------------*/ void ivas_ism_metadata_close( - ISM_METADATA_HANDLE hIsmMetaData[] /* i/o : object metadata handles */ + ISM_METADATA_HANDLE hIsmMetaData[] /* i/o : object metadata handles */ +#ifdef MASA_AND_OBJECTS + , + const int16_t first_idx /* i : index of first handle to deallocate */ +#endif ) { int16_t n; @@ -556,7 +674,11 @@ void ivas_ism_metadata_close( return; } +#ifdef MASA_AND_OBJECTS + for ( n = first_idx; n < MAX_NUM_OBJECTS; n++ ) +#else for ( n = 0; n < MAX_NUM_OBJECTS; n++ ) +#endif { if ( hIsmMetaData[n] != NULL ) { diff --git a/lib_com/ivas_masa_com.c b/lib_com/ivas_masa_com.c index b1a6c256d2a0eaf785e58ebadcc74dde392fd337..94d537494ed2cf1837d0cb02c154fca9bbe15daf 100644 --- a/lib_com/ivas_masa_com.c +++ b/lib_com/ivas_masa_com.c @@ -69,13 +69,19 @@ static int16_t quantize_phi_masa( float phi, const int16_t flag_delta, float *ph *---------------------------------------------------------------*/ void ivas_masa_set_elements( - const int32_t ivas_total_brate, /* i : codec total bitrate */ + const int32_t ivas_total_brate, /* i : IVAS total bitrate */ const int16_t mc_mode, /* i : MC format mode */ const int16_t nchan_transport, /* i : number of MASA input/transport channels */ IVAS_QMETADATA_HANDLE hQMetaData, /* i/o: q_metadata handle */ int16_t *element_mode, /* o : element mode */ int16_t *nSCE, /* o : number of SCEs */ int16_t *nCPE /* o : number of CPEs */ +#ifdef MASA_AND_OBJECTS + , + const int16_t ivas_format, /* i : IVAS format */ + const ISM_MODE ism_mode, /* i : ISM mode */ + const int32_t ism_total_brate /* i : initial ISM total bitrate */ +#endif ) { if ( nchan_transport == 2 ) @@ -87,17 +93,42 @@ void ivas_masa_set_elements( *element_mode = IVAS_SCE; /* This is needed for the initialization phase to initialize codec mode to SCE, since it is written first to the file*/ } +#ifdef MASA_AND_OBJECTS + else if ( ivas_format == MASA_ISM_FORMAT && ism_mode != ISM_MODE_NONE ) + { + *nCPE = 1; + + if ( *element_mode == -1 ) + { + *element_mode = IVAS_CPE_DFT; /* To have it initialized in case it was not already. */ + } + if ( ivas_total_brate > MIN_BRATE_MDCT_STEREO ) + { + *element_mode = IVAS_CPE_MDCT; + if ( ( ism_mode == ISM_MASA_MODE_DISC || ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ || ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) && ( ivas_total_brate - ism_total_brate < MIN_BRATE_MDCT_STEREO ) ) + { + *element_mode = IVAS_CPE_DFT; + } + } + } +#endif else { *nCPE = 1; *nSCE = 0; - if ( ivas_total_brate > IVAS_48k ) + if ( ivas_total_brate > MIN_BRATE_MDCT_STEREO ) { *element_mode = IVAS_CPE_MDCT; } } hQMetaData->bits_frame_nominal = (int16_t) ( ivas_total_brate / FRAMES_PER_SEC ); +#ifdef MASA_AND_OBJECTS + if ( ivas_format == MASA_ISM_FORMAT && ( ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ || ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ || ism_mode == ISM_MASA_MODE_DISC ) ) + { + hQMetaData->bits_frame_nominal -= (int16_t) ( ism_total_brate / FRAMES_PER_SEC ); + } +#endif } else if ( nchan_transport == 1 ) { @@ -187,7 +218,7 @@ void generate_gridEq( void ivas_masa_set_coding_config( MASA_CODEC_CONFIG *config, /* i/o: MASA coding config structure */ int16_t *band_mapping, /* o : Band mapping used */ - const int32_t ivas_total_brate, /* i : codec total bitrate */ + const int32_t ivas_total_brate, /* i : IVAS total bitrate */ const int16_t nchan_transport, /* i : number of transport channels (mono/stereo) */ const uint8_t isMcMasa /* i : toggle for selecting mcMASA specific config */ ) @@ -768,3 +799,207 @@ void deindex_sph_idx( return; } + + +#ifdef MASA_AND_OBJECTS +/*--------------------------------------------------------------- + * valid_ratio_index() + * + * Checking validity of the index of an ISM ratio index vector, + * within the indexing function. + *---------------------------------------------------------------*/ + +/*! r: valid or not 1/0 */ +int16_t valid_ratio_index( + int16_t index, /* i : index to be checked */ + const int16_t K, /* i : L1 norm to check against */ + const int16_t len /* i : vector length */ +) +{ + int16_t out; + int16_t i, sum, elem; + int16_t base[4]; + + sum = 0; + set_s( base, 1, len ); + + + for ( i = 1; i < len; i++ ) + { + base[i] = base[i - 1] * 10; + } + sum = 0; + for ( i = len - 1; i >= 0; i-- ) + { + elem = index / base[i]; + sum += elem; + index -= elem * base[i]; + } + if ( sum <= K ) + { + out = 1; + } + else + { + out = 0; + } + + return out; +} + + +/*--------------------------------------------------------------- + * reconstruct_ism_ratios() + * + * Obtains ISM ratio values from the quantized indexes + *---------------------------------------------------------------*/ + +void reconstruct_ism_ratios( + int16_t *ratio_ism_idx, /* i : index vector */ + const int16_t nchan_ism, /* i : number of components/objects */ + const float step, /* i : quantization step */ + float *q_energy_ratio_ism /* o : reconstructed ISM values */ +) +{ + int16_t i; + float sum; + + sum = 0; + for ( i = 0; i < nchan_ism - 1; i++ ) + { + q_energy_ratio_ism[i] = ratio_ism_idx[i] * step; + sum += q_energy_ratio_ism[i]; + } + + q_energy_ratio_ism[nchan_ism - 1] = 1.0f - sum; + + if ( q_energy_ratio_ism[nchan_ism - 1] < 0 ) + { + q_energy_ratio_ism[nchan_ism - 1] = 0.0f; + } + + return; +} + + +/*--------------------------------------------------------------- + * modify_masa_energy_ratios() + * + * Updates energy ratios by taking into account the MASA content contribution + * to the total audio scene + *---------------------------------------------------------------*/ + +void modify_masa_energy_ratios( + IVAS_QMETADATA_HANDLE hQMetaData /* i/o: Metadata handle */ +) +{ + int16_t i, m, d, b; + + for ( m = 0; m < MAX_PARAM_SPATIAL_SUBFRAMES; m++ ) + { + if ( hQMetaData->q_direction[0].cfg.nblocks == 1 ) + { + i = 0; + } + else + { + i = m; + } + + for ( b = 0; b < hQMetaData->q_direction[0].cfg.nbands; b++ ) + { + for ( d = 0; d < hQMetaData->no_directions; d++ ) + { + hQMetaData->q_direction[d].band_data[b].energy_ratio[m] = hQMetaData->q_direction[d].band_data[b].energy_ratio[m] * hQMetaData->masa_to_total_energy_ratio[i][b]; + } + } + } + + return; +} + + +/*--------------------------------------------------------------- + * distribute_evenly_ism() + * + * Obtain ISM ratio indexes for even content distribution bbetween objects + *---------------------------------------------------------------*/ + +void distribute_evenly_ism( + int16_t *idx, /* o : index values */ + const int16_t K, /* i : sum of indexes */ + const int16_t nchan_ism /* i : number of objects */ +) +{ + int16_t i; + int16_t sum; + + sum = 0; + for ( i = 0; i < nchan_ism; i++ ) + { + idx[i] = (int16_t) ( K / nchan_ism ); + sum += idx[i]; + } + + assert( sum <= K ); + + i = 0; + while ( sum < K ) + { + if ( i == nchan_ism ) + { + i = 0; + } + idx[i]++; + sum++; + i++; + } + + return; +} + + +/*--------------------------------------------------------------- + * calculate_cpe_brate_MASA_ISM() + * + * Calculates bitrate for MASA_ISM mode that is not used for separated objects, + * * but for the CPE part (metadata included) + *---------------------------------------------------------------*/ + +/*! r: CPE bitrate value */ +int32_t calculate_cpe_brate_MASA_ISM( + const ISM_MODE ism_mode, /* i : ism mode */ + const int32_t ivas_total_brate, /* i : IVAS total bitrate */ + const int16_t nchan_ism /* i : number of objects */ +) +{ + int32_t cpe_brate; + int16_t k, sce_id; + + k = 0; + while ( k < SIZE_IVAS_BRATE_TBL && ivas_total_brate != ivas_brate_tbl[k] ) + { + k++; + } + + if ( ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ || ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) + { + cpe_brate = ivas_total_brate - sep_object_brate[k - 2][0]; /* take data from the first column */ + } + else if ( ism_mode == ISM_MASA_MODE_DISC ) + { + cpe_brate = ivas_total_brate; + + for ( sce_id = 0; sce_id < nchan_ism; sce_id++ ) + { + cpe_brate -= sep_object_brate[k - 2][nchan_ism - 1]; + } + } + else + { + cpe_brate = ivas_total_brate; + } + + return cpe_brate; +} +#endif diff --git a/lib_com/ivas_mcmasa_com.c b/lib_com/ivas_mcmasa_com.c index 1b7db4ff01a7c1426c65eb74c0cba4ab76cc8eaa..7e81e1fd1cd8317beeb8c359c34433a113896e02 100644 --- a/lib_com/ivas_mcmasa_com.c +++ b/lib_com/ivas_mcmasa_com.c @@ -101,7 +101,7 @@ void ivas_mcmasa_set_separate_channel_mode( void ivas_mcmasa_split_brate( const uint8_t separateChannelEnabled, /* i : Transport running in "separate channel" mode */ - const int32_t ivas_total_brate, /* i : Total bitrate available to be split */ + const int32_t ivas_total_brate, /* i : IVAS total bitrate available to be split */ const int16_t nSCE, /* i : Number of SCEs in use (0 or 1) */ const int16_t nCPE, /* i : Number of CPEs in use (0 or 1) */ int32_t *brate_sce, /* o : Pointer to SCE element bitrate */ diff --git a/lib_com/ivas_omasa_com.c b/lib_com/ivas_omasa_com.c new file mode 100644 index 0000000000000000000000000000000000000000..8e385537c3738d0099c6f0ff060192ff4ba7eb0d --- /dev/null +++ b/lib_com/ivas_omasa_com.c @@ -0,0 +1,523 @@ +/****************************************************************************************************** + + (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +#include "options.h" +#include +#include "ivas_cnst.h" +#include "ivas_prot.h" +#include "prot.h" +#include "ivas_rom_com.h" +#include +#ifdef DEBUGGING +#include "debug.h" +#endif + +#ifdef MASA_AND_OBJECTS +/*--------------------------------------------------------------- + * Local constants + *---------------------------------------------------------------*/ + +#define GAMMA_ISM_LOW_IMP 0.8f +#define GAMMA_ISM_MEDIUM_IMP 1.2f +#define GAMMA_ISM_HIGH_IMP 1.4f + +#define GAMMA_ISM_LOW_IMP2 0.9f +#define GAMMA_ISM_MEDIUM_IMP2 1.2f +#define GAMMA_ISM_HIGH_IMP2 1.35f + +#define GAMMA_ISM_LOW_IMP3 0.85f +#define GAMMA_ISM_MEDIUM_IMP3 1.15f +#define GAMMA_ISM_HIGH_IMP3 1.3f + +#define GAMMA_ISM_LOW_IMP4 0.8f +#define GAMMA_ISM_MEDIUM_IMP4 1.0f +#define GAMMA_ISM_HIGH_IMP4 1.2f + + +/*--------------------------------------------------------------- + * ivas_omasa_ism_mode_select() + * + * selects the ISM mode base on IVAS total bit-rate and + * the number of objects in the combined ISM MASA format mode + * ---------------------------------------------------------------*/ + +/*! r : ISM format mode */ +ISM_MODE ivas_omasa_ism_mode_select( + const int32_t ivas_total_brate, /* i : IVAS total bitrate */ + const int16_t nchan_ism /* i : number of input ISM's */ +) +{ + ISM_MODE ism_mode = ISM_MODE_NONE; + + switch ( nchan_ism ) + { + case 1: + if ( ivas_total_brate >= IVAS_24k4 ) + { + ism_mode = ISM_MASA_MODE_DISC; + } + else + { + ism_mode = ISM_MODE_NONE; + } + break; + case 2: + if ( ivas_total_brate >= IVAS_48k ) + { + ism_mode = ISM_MASA_MODE_DISC; + } + else if ( ivas_total_brate >= IVAS_32k ) + { + ism_mode = ISM_MASA_MODE_PARAM_ONE_OBJ; + } + else + { + ism_mode = ISM_MODE_NONE; + } + break; + case 3: + if ( ivas_total_brate >= IVAS_96k ) + { + ism_mode = ISM_MASA_MODE_DISC; + } + else if ( ivas_total_brate >= IVAS_64k ) + { + ism_mode = ISM_MASA_MODE_PARAM_ONE_OBJ; + } + else if ( ivas_total_brate >= IVAS_32k ) + { + ism_mode = ISM_MASA_MODE_MASA_ONE_OBJ; + } + else + { + ism_mode = ISM_MODE_NONE; + } + break; + case 4: + if ( ivas_total_brate >= IVAS_128k ) + { + ism_mode = ISM_MASA_MODE_DISC; + } + else if ( ivas_total_brate >= IVAS_64k ) + { + ism_mode = ISM_MASA_MODE_PARAM_ONE_OBJ; + } + else if ( ivas_total_brate >= IVAS_32k ) + { + ism_mode = ISM_MASA_MODE_MASA_ONE_OBJ; + } + else + { + ism_mode = ISM_MODE_NONE; + } + break; + } + + return ism_mode; +} + + +/*--------------------------------------------------------------- + * ivas_set_omasa_TC() + * + * set number of transport channels in OMASA format + * ---------------------------------------------------------------*/ + +void ivas_set_omasa_TC( + const ISM_MODE ism_mode, /* i : ISM mode */ + const int16_t nchan_ism, /* i : number of input ISMs */ + int16_t *nSCE, /* o : number of SCEs */ + int16_t *nCPE /* o : number of CPEs */ +) +{ + switch ( ism_mode ) + { + case ISM_MASA_MODE_MASA_ONE_OBJ: + case ISM_MASA_MODE_PARAM_ONE_OBJ: + *nCPE = 1; + *nSCE = 1; + break; + case ISM_MASA_MODE_DISC: + *nCPE = 1; + *nSCE = nchan_ism; + break; + case ISM_MODE_NONE: + *nCPE = 1; + *nSCE = 0; + break; + default: + break; + } + + return; +} + + +/*--------------------------------------------------------------- + * ivas_interformat_brate() + * + * Bit-budget distribution in case of combined-format coding + * ---------------------------------------------------------------*/ + +/*! r: adjusted bitrate */ +int32_t ivas_interformat_brate( + const ISM_MODE ism_mode, /* i : ISM mode */ + const int16_t nchan_ism, /* i : number of ISM channels */ + const int32_t element_brate, /* i : element bitrate */ + const int16_t ism_imp, /* i : ISM importance flag */ + const int16_t limit_flag /* i : flag to limit the bitrate increase */ +) +{ + int32_t element_brate_out; + int16_t nBits, limit_low, limit_high; + + nBits = (int16_t) ( element_brate / FRAMES_PER_SEC ); + + if ( ism_imp == ISM_INACTIVE_IMP ) + { + nBits = BITS_ISM_INACTIVE; + } + else + { + if ( ism_mode == ISM_MASA_MODE_DISC && ( ( nchan_ism == 4 && element_brate == 24000 ) || ( nchan_ism == 3 && element_brate <= 24000 ) || ( nchan_ism == 2 && element_brate <= 11000 ) ) ) /* for border case in DISC mode */ + { + if ( limit_flag == 1 && ( ( nchan_ism == 4 && element_brate == 24000 ) || ( nchan_ism == 3 && element_brate == 20000 ) || ( nchan_ism == 2 && element_brate <= 11000 ) ) ) + { + return element_brate; + } + + if ( ism_imp == ISM_LOW_IMP ) + { + nBits = (int16_t) ( nBits * GAMMA_ISM_LOW_IMP4 ); + } + else if ( ism_imp == ISM_MEDIUM_IMP ) + { + nBits = (int16_t) ( nBits * GAMMA_ISM_MEDIUM_IMP4 ); + if ( limit_flag == -1 ) + { + nBits = (int16_t) ( nBits * GAMMA_ISM_HIGH_IMP4 ); + } + } + else /* ISM_HIGH_IMP */ + { + nBits = (int16_t) ( nBits * GAMMA_ISM_HIGH_IMP4 ); + if ( limit_flag == -1 ) + { + nBits = (int16_t) ( nBits * GAMMA_ISM_HIGH_IMP4 ); + } + } + } + else if ( ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ || + ( ism_mode == ISM_MASA_MODE_DISC && element_brate == 9600 ) /* this condition corresponds to the ivas_total_brate = 24400 and 1 object */ + ) + { + if ( ism_imp == ISM_LOW_IMP ) + { + nBits = (int16_t) ( nBits * GAMMA_ISM_LOW_IMP3 ); + } + else if ( ism_imp == ISM_MEDIUM_IMP ) + { + nBits = (int16_t) ( nBits * GAMMA_ISM_MEDIUM_IMP3 ); + } + else /* ISM_HIGH_IMP */ + { + nBits = (int16_t) ( nBits * GAMMA_ISM_HIGH_IMP3 ); + } + } + else + { + if ( ism_imp == ISM_LOW_IMP ) + { + nBits = (int16_t) ( nBits * GAMMA_ISM_LOW_IMP ); + } + else if ( ism_imp == ISM_MEDIUM_IMP ) + { + nBits = (int16_t) ( nBits * GAMMA_ISM_MEDIUM_IMP ); + } + else /* ISM_HIGH_IMP */ + { + nBits = (int16_t) ( nBits * GAMMA_ISM_HIGH_IMP ); + } + } + } + + limit_low = MIN_BRATE_SWB_BWE / FRAMES_PER_SEC; + if ( ism_imp == ISM_INACTIVE_IMP ) + { + limit_low = BITS_ISM_INACTIVE; + } + else if ( element_brate >= SCE_CORE_16k_LOW_LIMIT ) + { + limit_low = SCE_CORE_16k_LOW_LIMIT / FRAMES_PER_SEC; + } + + limit_high = IVAS_512k / FRAMES_PER_SEC; + if ( element_brate < SCE_CORE_16k_LOW_LIMIT ) + { + limit_high = ACELP_12k8_HIGH_LIMIT / FRAMES_PER_SEC; + } + + nBits = check_bounds_s( nBits, limit_low, limit_high ); + + element_brate_out = nBits * FRAMES_PER_SEC; + + return element_brate_out; +} + + +/*--------------------------------------------------------------- + * ivas_combined_format_brate_sanity() + * + * Sanity check in combined format coding + * ---------------------------------------------------------------*/ + +void ivas_combined_format_brate_sanity( + const int32_t element_brate, /* i : element bitrate */ + const int16_t core, /* i : core */ + int32_t *core_brate, /* i/o: core bitrate */ + int16_t *diff_nBits /* o : number of differential bits */ +) +{ + int16_t limit_high, nBits; + + /* sanity check: at lowest IVAS bit-rates and one ISM channel coded by + low-rate core-coder mode, it can happen that the CPE (MASA) bit-budget + for ACELP core-coding @12.8 kHz is too high */ + + if ( element_brate < ACELP_12k8_HIGH_LIMIT ) + { + limit_high = ACELP_12k8_HIGH_LIMIT / FRAMES_PER_SEC; + nBits = (int16_t) ( *core_brate / FRAMES_PER_SEC ); + + *diff_nBits = nBits - limit_high; + if ( *diff_nBits > 0 ) + { + if ( core == TCX_20_CORE || core == TCX_10_CORE ) + { + *diff_nBits = 0; + } + else /* ACELP core */ + { + *core_brate -= ( *diff_nBits * FRAMES_PER_SEC ); + } + } + } + + return; +} + + +/*--------------------------------------------------------------- + * bits_index_ism_ratio() + * + * + * ---------------------------------------------------------------*/ + +/*!r : number of bits for ISM ratio index */ +int16_t bits_index_ism_ratio( + const int16_t nchan_ism /* i : number of objects */ +) +{ + int16_t bits_index; + + bits_index = 0; + if ( nchan_ism == 2 ) + { + bits_index = 3; + } + else if ( nchan_ism == 3 ) + { + bits_index = 6; + } + else if ( nchan_ism == 4 ) + { + bits_index = 7; + } + else + { + assert( ( nchan_ism >= 2 && nchan_ism <= 4 ) && "Wrong number of objects for MASA_ISM." ); + } + + return bits_index; +} + + +/*--------------------------------------------------------------- + * calculate_nbits_meta() + * + * + * ---------------------------------------------------------------*/ + +void calculate_nbits_meta( + const int16_t nchan_ism, + float q_energy_ratio_ism[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS], + float masa_to_total_energy_ratio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], + const int16_t numSf, + const int16_t numCodingBands, + int16_t *bits_ism, + const int16_t idx_sep_obj, + const int16_t ism_imp ) +{ + int16_t sf, band, obj; + float priority[MAX_NUM_OBJECTS], max_p; + + if ( nchan_ism > 1 ) + { + set_f( priority, 0.0f, nchan_ism ); + for ( sf = 0; sf < numSf; sf++ ) + { + for ( band = 0; band < numCodingBands; band++ ) + { + for ( obj = 0; obj < nchan_ism; obj++ ) + { + priority[obj] = max( priority[obj], ( q_energy_ratio_ism[sf][band][obj] * ( 1 - masa_to_total_energy_ratio[sf][band] ) ) ); + } + } + } + } + else + { + priority[0] = 1; + } + + /* decide parameters for ISM metadata quantization */ + maximum( priority, nchan_ism, &max_p ); + for ( obj = 0; obj < nchan_ism; obj++ ) + { + if ( obj == idx_sep_obj ) + { + if ( ism_imp == 3 ) + { + priority[obj] = 1; + } + else if ( ism_imp == 2 ) + { + priority[obj] = ( 1 + max_p ) * 0.5f; + } + else + { + priority[obj] = max_p; + } + } + bits_ism[obj] = bits_direction_masa[0] - (int16_t) ( ( 1 - ( (int16_t) ( priority[obj] * 1000.0f ) ) * 0.001f ) * 6 ); + } + + return; +} + + +/*--------------------------------------------------------------- + * ivas_get_stereo_panning_gains() + * + * + *---------------------------------------------------------------*/ + +void ivas_get_stereo_panning_gains( + const float aziDeg, + const float eleDeg, + float panningGains[2] ) +{ + float aziRad, eleRad; + float y, mappedX, aziRadMapped, A, A2, A3; + const float LsAngleRad = 30.0f * PI_OVER_180; + /* Convert azi and ele to an azi value of the cone of confusion */ + aziRad = aziDeg * PI_OVER_180; + eleRad = eleDeg * PI_OVER_180; + y = ( sinf( aziRad ) * cosf( eleRad ) ); + mappedX = sqrtf( max( 0.0f, 1.0f - ( y * y ) ) ); + aziRadMapped = atan2f( y, mappedX ); + + if ( aziRadMapped >= LsAngleRad ) + { /* Left side */ + panningGains[0] = 1.0f; + panningGains[1] = 0.0f; + } + else if ( aziRadMapped <= -LsAngleRad ) + { /* Right side */ + panningGains[0] = 0.0f; + panningGains[1] = 1.0f; + } + else /* Tangent panning law */ + { + A = tanf( aziRadMapped ) / tanf( LsAngleRad ); + A2 = ( A - 1.0f ) / max( 0.001f, A + 1.0f ); + A3 = 1.0f / ( A2 * A2 + 1.0f ); + panningGains[0] = sqrtf( A3 ); + panningGains[1] = sqrtf( 1.0f - A3 ); + } + + return; +} + + +/*--------------------------------------------------------------- + * calculate_brate_limit_flag() + * + * + *---------------------------------------------------------------*/ + +/*! r: limitation flag */ +int16_t calculate_brate_limit_flag( + const int16_t ism_imp[], /* i : ISM importance flags */ + const int16_t nchan_ism /* i : number of objects */ +) +{ + int16_t n; + int16_t brate_limit_flag; + int16_t nzeros; + + brate_limit_flag = 0; + nzeros = 0; + for ( n = 0; n < nchan_ism; n++ ) + { + brate_limit_flag += ism_imp[n]; + if ( ism_imp[n] == 0 ) + { + nzeros++; + } + } + + if ( brate_limit_flag >= (int16_t) ( nchan_ism * 2.5f ) ) + { + brate_limit_flag = 1; + } + else + { + if ( nzeros / (float) nchan_ism >= 0.5f ) + { + brate_limit_flag = -1; /* there is no limitation, on the contrary */ + } + } + + return brate_limit_flag; +} +#endif diff --git a/lib_com/ivas_prot.h b/lib_com/ivas_prot.h index 885de082817bae5459551d03c98c3aaf853071b5..63395cccd7b89c85ec5dd6096fdc1b5ae2a44a92 100644 --- a/lib_com/ivas_prot.h +++ b/lib_com/ivas_prot.h @@ -109,9 +109,9 @@ ivas_error mct_enc_reconfigure( ivas_error ivas_spar_md_enc_init ( - ivas_spar_md_enc_state_t *hMdEnc, /* o : MD encoder handle */ - const ENCODER_CONFIG_HANDLE hEncoderConfig, /* i : configuration structure */ - const int16_t sba_order /* i : Ambisonic (SBA) order */ + ivas_spar_md_enc_state_t *hMdEnc, /* o : MD encoder handle */ + const ENCODER_CONFIG_HANDLE hEncoderConfig, /* i : configuration structure */ + const int16_t sba_order /* i : Ambisonic (SBA) order */ ); ivas_error ivas_sba_enc_reconfigure( @@ -789,8 +789,8 @@ ivas_error ivas_jbm_dec_flush_renderer( ivas_error ivas_jbm_dec_feed_tc_to_renderer( Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ - const int16_t nSamplesForRendering, /* i : number of TC samples available for rendering */ - int16_t *nSamplesResidual, /* o : number of samples not fitting into the renderer grid and buffer for the next call*/ + const int16_t nSamplesForRendering, /* i : number of TC samples available for rendering */ + int16_t *nSamplesResidual, /* o : number of samples not fitting into the renderer grid and buffer for the next call*/ float *data /* i/o: transport channels/output synthesis signal */ ); @@ -900,7 +900,18 @@ ivas_error ivas_ism_config( int32_t element_brate[], /* o : element bitrate per object */ int32_t total_brate[], /* o : total bitrate per object */ int16_t nb_bits_metadata[] /* i/o: number of metadata bits */ +#ifdef MASA_AND_OBJECTS + , const int16_t combined_format_flag /* i : flag indicating combined format */ +#endif +); + +#ifdef MASA_AND_OBJECTS +void bitbudget_to_brate( + const int16_t x[], /* i : bitbudgets */ + int32_t y[], /* o : bitrates */ + const int16_t N /* i : number of entries to be converted */ ); +#endif void ivas_ism_reset_metadata( ISM_METADATA_HANDLE hIsmMeta /* i/o: ISM metadata handles */ @@ -956,10 +967,18 @@ ivas_error ivas_ism_enc( float data[MAX_NUM_OBJECTS][L_FRAME48k], /* i : input signal */ const int16_t input_frame, /* i : input frame length per channel */ int16_t *nb_bits_metadata /* i : number of metadata bits */ +#ifdef MASA_AND_OBJECTS + , + const int16_t flag_omasa_ener_brate /* i : less bitrate for objects in OMASA flag */ +#endif ); ivas_error ivas_ism_metadata_enc( +#ifdef MASA_AND_OBJECTS + int32_t *ism_total_brate, /* i/o: ISM total bitrate */ +#else const int32_t ism_total_brate, /* i : ISM total bitrate */ +#endif const int16_t nchan_ism, /* i : number of ISM channels */ const int16_t nchan_transport, /* i : number of transport channels */ ISM_METADATA_HANDLE hIsmMeta[], /* i/o: ISM metadata handles */ @@ -970,6 +989,12 @@ ivas_error ivas_ism_metadata_enc( const int16_t ism_mode, /* i : ISM mode */ const PARAM_ISM_CONFIG_HANDLE hParamIsm, /* i : Param ISM Config Handle */ const int16_t ism_extended_metadata_flag /* i : Extended metadata flag */ +#ifdef MASA_AND_OBJECTS + , + const float lp_noise_CPE, /* i : LP filterend total noise estimation */ + const int16_t flag_omasa_ener_brate, /* i : less bitrate for objects in OMASA flag */ + int16_t *omasa_stereo_sw_cnt +#endif ); ivas_error ivas_ism_metadata_dec( @@ -1015,6 +1040,10 @@ void ivas_param_ism_enc_close( void ivas_ism_metadata_close( ISM_METADATA_HANDLE hIsmMetaData[] /* i/o : object metadata handles */ +#ifdef MASA_AND_OBJECTS + , + const int16_t first_idx /* i : index of first handle to deallocate */ +#endif ); void ivas_param_ism_stereo_dmx( @@ -1045,7 +1074,6 @@ ivas_error ivas_param_ism_dec_open( void ivas_param_ism_dec_close( DIRAC_DEC_HANDLE *hDirAC, /* i/o: decoder DirAC handle */ - SPAT_PARAM_REND_COMMON_DATA_HANDLE *hSpatParamRendCom_out, /* i/o: common spatial renderer data */ const AUDIO_CONFIG output_config /* i : output audio configuration */ ); @@ -1060,8 +1088,8 @@ void ivas_ism_dec_digest_tc( void ivas_param_ism_dec_digest_tc( Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ - const uint16_t nCldfbSlots, /* i : number of CLFBS slots in the transport channels */ - float *transport_channels_f[] /* i : synthesized core-coder transport channels/DirAC output */ + const uint16_t nCldfbSlots, /* i : number of CLFBS slots in the transport channels */ + float *transport_channels_f[] /* i : synthesized core-coder transport channels/DirAC output */ ); void ivas_param_ism_dec_render( @@ -1925,7 +1953,11 @@ void stereo_tdm_prep_dwnmx ( const float *input1, /* i : right channel input */ const int16_t input_frame /* i : frame lenght */ ); + int16_t stereo_tdm_ener_analysis( +#ifdef MASA_AND_OBJECTS + const int16_t ivas_format, /* i : IVAS format */ +#endif CPE_ENC_HANDLE hCPE, /* i : CPE structure */ const int16_t input_frame, /* i : Number of samples */ int16_t *tdm_SM_or_LRTD_Pri, /* o : channel combination scheme flag in TD stereo OR LRTD primary channel */ @@ -1948,6 +1980,10 @@ void stereo_td_init_dec( ); void tdm_configure_dec( +#ifdef MASA_AND_OBJECTS + const int16_t ivas_format, /* i : IVAS format */ + const int16_t ism_mode, /* i : ISM mode in combined format */ +#endif CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */ int16_t *tdm_ratio_idx, /* o : ratio index */ const int16_t nb_bits_metadata /* i : number of metadata bits */ @@ -1997,6 +2033,10 @@ void tdm_ol_pitch_comparison( ); void tdm_configure_enc( +#ifdef MASA_AND_OBJECTS + const int16_t ivas_format, /* i : IVAS format */ + const int16_t ism_mode, /* i : ISM mode in combined format */ +#endif CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */ const float Etot_last[CPE_CHANNELS], /* i/o: Energy of last frame */ const int16_t tdm_SM_or_LRTD_Pri, /* i : channel combination scheme flag in TD stereo OR LRTD primary channel */ @@ -2013,6 +2053,10 @@ ivas_error signaling_enc_secondary( ); void tdm_bit_alloc( +#ifdef MASA_AND_OBJECTS + const int16_t ivas_format, /* i : IVAS format */ + const int16_t ism_mode, /* i : ISM mode in combined format */ +#endif const int32_t element_brate_wo_meta, /* i : element bitrate without metadata */ const int16_t tdm_lp_reuse_flag, /* i : LPC reusage flag */ int32_t *total_brate_pri, /* o : Allocated primary channel bitrate */ @@ -3171,9 +3215,8 @@ int16_t ivas_qmetadata_dec_sid_decode( void ivas_qmetadata_to_dirac( const IVAS_QMETADATA_HANDLE hQMetaData, /* i : frame of MASA q_metadata */ - DIRAC_DEC_HANDLE hDirAC, /* i : DirAC decoder structure */ + DIRAC_DEC_HANDLE hDirAC, /* o : DirAC decoder structure */ MASA_DECODER_HANDLE hMasa, /* i : MASA decoder structure */ - SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, /* i/o: common spatial renderer data handle */ const int32_t ivas_total_brate, /* i : IVAS total bitrate */ const IVAS_FORMAT ivas_format, /* i : IVAS format */ const int16_t hodirac_flag, /* i : flag to indicate HO-DirAC mode */ @@ -3501,7 +3544,7 @@ void ivas_sba_dirac_stereo_smooth_parameters( ivas_spar_md_dec_state_t *hMdDec, /* i/o: SPAR MD handle for upmixing */ const int16_t cross_fade_start_offset, /* i : SPAR mixer delay compensation */ const int32_t output_Fs, /* i : Fs for delay calculation */ - const int16_t num_md_sub_frames /* i : number of subframes in mixing matrix */ + const int16_t num_md_sub_frames /* i : number of subframes in mixing matrix */ ); void ivas_sba2mc_cldfb( @@ -3537,12 +3580,12 @@ void ivas_dirac_enc( IVAS_QMETADATA_HANDLE hQMetaData, /* i/o: q_metadata handle */ BSTR_ENC_HANDLE hMetaData, /* i/o: Metadata bitstream handle */ float data_f[][L_FRAME48k], /* i/o: SBA channels */ - float **ppIn_FR_real, /* o : real freq domain values */ - float **ppIn_FR_imag, /* o : imag freq domain values */ - const int16_t input_frame, /* i : input frame length */ - const int16_t dtx_vad, /* i : DTX vad flag */ - const IVAS_FORMAT ivas_format, /* i : ivas format */ - int16_t hodirac_flag /* i : hodirac flag */ + float **ppIn_FR_real, /* o : real freq domain values */ + float **ppIn_FR_imag, /* o : imag freq domain values */ + const int16_t input_frame, /* i : input frame length */ + const int16_t dtx_vad, /* i : DTX vad flag */ + const IVAS_FORMAT ivas_format, /* i : ivas format */ + int16_t hodirac_flag /* i : hodirac flag */ ); ivas_error ivas_dirac_config( void *st_ivas, /* i/o: IVAS encoder/decoder state structure */ @@ -3575,20 +3618,33 @@ ivas_error ivas_dirac_sba_config( const int16_t nbands /* i : number of frequency bands */ ); +ivas_error ivas_dirac_dec_open( + Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ +); + +ivas_error ivas_dirac_allocate_parameters( + DIRAC_DEC_HANDLE hDirAC, /* i/o: decoder DirAC handle */ + const int16_t params_flag /* i : set of parameters flag */ +); + ivas_error ivas_dirac_dec_config( Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ const DIRAC_CONFIG_FLAG flag_configopen /* i/ : Flag determining if we open or reconfigure the DirAC decoder */ ); void ivas_dirac_dec_close( - DIRAC_DEC_HANDLE *hDirAC_out + DIRAC_DEC_HANDLE *hDirAC /* i/o: decoder DirAC handle */ +); + +void ivas_dirac_deallocate_parameters( + DIRAC_DEC_HANDLE hDirAC, /* i/o: decoder DirAC handle */ + const int16_t params_flag /* i : set of parameters flag */ ); void ivas_dirac_dec_read_BS( const int32_t ivas_total_brate, /* i : IVAS total bitrate */ Decoder_State *st, /* i/o: decoder Core state structure */ DIRAC_DEC_HANDLE hDirAC, /* i/o: decoder DirAC handle */ - SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, /* i/o: common spatial rendering data handle */ IVAS_QMETADATA_HANDLE hQMetaData, /* i/o: q metadata */ int16_t *nb_bits, /* o : number of bits read */ const int16_t hodirac_flag, /* i : flag to indicate HO-DirAC mode */ @@ -3639,6 +3695,12 @@ ivas_error ivas_td_decorr_reconfig_dec( uint16_t *useTdDecorr /* i/o: TD decorrelator flag */ ); +/*! r: Configured reqularization factor value */ +float configure_reqularization_factor( + const IVAS_FORMAT ivas_format, /* i : IVAS format */ + const int32_t ivas_total_brate /* i : total IVAS bitrate */ +); + void computeDiffuseness_mdft( float **buffer_intensity[DIRAC_NUM_DIMS], const float *buffer_energy, @@ -3665,6 +3727,109 @@ void computeDiffuseness( float *diffuseness ); +ivas_error ivas_dirac_dec_onset_detection_open( + const int16_t num_channels, + const int16_t num_freq_bands, + const int16_t max_band_decorr, + DIRAC_ONSET_DETECTION_PARAMS *ph_dirac_onset_detection_params, + DIRAC_ONSET_DETECTION_STATE *ph_dirac_onset_detection_state +); + +void ivas_dirac_dec_onset_detection_process( + const float *input_power_f, + float *onset_filter, + const int16_t num_protos_diff, + DIRAC_ONSET_DETECTION_PARAMS h_dirac_onset_detection_params, + DIRAC_ONSET_DETECTION_STATE h_dirac_onset_detection_state +); + +ivas_error ivas_dirac_dec_decorr_open( + DIRAC_DECORR_PARAMS **ph_freq_domain_decorr_ap_params, + DIRAC_DECORR_STATE **ph_freq_domain_decorr_ap_state, + const int16_t num_freq_bands, + int16_t num_outputs_diff, + const int16_t num_protos_diff, + const DIRAC_SYNTHESIS_CONFIG synthesisConf, + float *frequency_axis, + const int16_t nchan_transport, /* i : number of transport channels */ + const int32_t output_Fs /* i : output sampling rate */ +); + +void ivas_dirac_dec_decorr_process( + const int16_t num_freq_bands, + int16_t num_channels, + const int16_t num_protos_diff, + const DIRAC_SYNTHESIS_CONFIG synthesisConf, + const int16_t nchan_transport, /* i : number of transport channels */ + const float *input_frame_f, + const int16_t num_protos_dir, + const int16_t *proto_index_dir, + float *frame_dec_f, + float *onset_filter, + HANDLE_DIRAC_DECORR_PARAMS h_freq_domain_decorr_ap_params, + HANDLE_DIRAC_DECORR_STATE h_freq_domain_decorr_ap_state +); + +void ivas_dirac_dec_decorr_close( + HANDLE_DIRAC_DECORR_PARAMS *ph_dirac_decorr_params, + HANDLE_DIRAC_DECORR_STATE *ph_dirac_decorr_state +); + +ivas_error ivas_dirac_dec_output_synthesis_open( + DIRAC_DEC_HANDLE hDirAC, /* i/o: DirAC handle */ + const RENDERER_TYPE renderer_type, /* i : renderer type */ + const int16_t nchan_transport, /* i : number of transport channels */ + const int32_t output_Fs /* i : output sampling rate */ + , + const int16_t hodirac_flag /* i : flag to indicate HO-DirAC mode */ +); + +void ivas_dirac_dec_output_synthesis_init( + DIRAC_DEC_HANDLE hDirAC, /* i/o: DirAC handle */ + const int16_t nchan_out_woLFE, /* i : number of output audio channels without LFE */ + const int16_t hodirac_flag /* i : flag to indicate HO-DirAC mode */ +); + +void ivas_dirac_dec_output_synthesis_close( + DIRAC_DEC_HANDLE hDirAC /* i/o: DirAC handle */ +); + +void ivas_dirac_dec_output_synthesis_process_slot( + const float *reference_power, /* i : Estimated power */ + const float *onset, /* i : onset filter */ + const int16_t *azimuth, + const int16_t *elevation, + const float *diffuseness, + DIRAC_DEC_HANDLE hDirAC, /* i/o: DirAC handle */ + const int16_t sh_rot_max_order, + const float *p_Rmat, /* i : rotation matrix */ + const VBAP_HANDLE hVBAPdata, /* i : VBAP structure */ + const IVAS_OUTPUT_SETUP hOutSetup, /* i : output setup structure */ + const int16_t nchan_transport, /* i : number of transport channels */ + const int16_t ind_slot, /* i : index of the slot to be added to the input covariance */ + const int16_t hodirac_flag /* i : flag to indicate HO-DirAC mode */ +); + +void ivas_dirac_dec_output_synthesis_process_subframe_gain_shd( + float RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX],/* i : LS signals */ + float ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX],/* i : LS signals */ + DIRAC_DEC_HANDLE hDirAC, /* i/o: DirAC handle */ + const int16_t nchan_transport, /* i : number of transport channels */ + const int16_t nbslots, /* i : number of slots to process */ + const float *onset_filter, + float *diffuseness, + const int16_t hodirac_flag /* i : flag to indicate HO-DirAC mode */ +); + +void ivas_dirac_dec_output_synthesis_process_subframe_psd_ls( + float RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX],/* i : LS signals */ + float ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX],/* i : LS signals */ + DIRAC_DEC_HANDLE hDirAC, /* i/o: DirAC handle */ + const int16_t nbslots, /* i : number of slots to process */ + float *diffuseness_vector, /* i : diffuseness (needed for direction smoothing)*/ + float *reference_power_smooth, + float qualityBasedSmFactor +); void ivas_dirac_dec_get_response( const int16_t azimuth, @@ -3673,54 +3838,99 @@ void ivas_dirac_dec_get_response( const int16_t ambisonics_order ); +void compute_hoa_encoder_mtx( + const float *azimuth, + const float *elevation, + float *response, + const int16_t num_responses, + const int16_t ambisonics_order ); + +void ivas_dirac_dec_compute_gain_factors( + const int16_t num_freq_bands, + const float *diffuseness, + const int16_t max_band_decorr, + float *direct_gain_factor, + float *diffuse_gain_factor +); + +void ivas_dirac_dec_compute_power_factors( + const int16_t num_freq_bands, + const float *diffuseness, + const int16_t max_band_decorr, + float *direct_power_factor, + float *diffuse_power_factor +); + +void ivas_dirac_dec_compute_directional_responses( + DIRAC_DEC_HANDLE hDirAC, /* i/o: DirAC handle */ + const VBAP_HANDLE hVBAPdata, /* i : VBAP structure */ + const MASA_DECODER_HANDLE hMasa, /* i : MASA decoder structure */ +#ifdef MASA_AND_OBJECTS + MASA_ISM_DATA_HANDLE hMasaIsm, /* i : MASA_ISM data structure */ +#endif + const int16_t *azimuth, + const int16_t *elevation, + const int16_t md_idx, + const float *surCohRatio, + const int16_t shd_rot_max_order, /* i : split-order rotation method */ + const float *p_Rmat, /* i : rotation matrix */ + const int16_t hodirac_flag /* i : flag to indicate HO-DirAC mode */ +); + +void ivas_dirac_dec_get_frequency_axis( + float *frequency_axis, /* o : array of center frequencies of a real filter bank */ + const int32_t output_Fs, /* i : sampling frequency */ + const int16_t num_freq_bands /* i : number of frequency bands */ +); + void calculate_hodirac_sector_parameters( - DIRAC_ENC_HANDLE hDirAC, - float RealBuffer[DIRAC_MAX_ANA_CHANS][DIRAC_NO_FB_BANDS_MAX],/* i : signal vector (L+1)^2 x N_bins, real part */ - float ImagBuffer[DIRAC_MAX_ANA_CHANS][DIRAC_NO_FB_BANDS_MAX],/* i : signal vector, imaginary part */ - const float beta, /* i : forgetting factor for average filtering */ - const int16_t *band_grouping, /* i : indices of band groups */ - const int16_t N_bands, /* i : number of bands (groups) */ - const int16_t enc_param_start_band, /* i : first band to process */ - float *azi, /* o : array of sector azimuth angles, flat */ - float *ele, /* o : array of sector elevation angles, flat */ - float *diff, /* o : array of sector diffuseness values, flat */ - float *ene /* o : array of sector energy values, flat */ + DIRAC_ENC_HANDLE hDirAC, + float RealBuffer[DIRAC_MAX_ANA_CHANS][DIRAC_NO_FB_BANDS_MAX],/* i : signal vector (L+1)^2 x N_bins, real part */ + float ImagBuffer[DIRAC_MAX_ANA_CHANS][DIRAC_NO_FB_BANDS_MAX],/* i : signal vector, imaginary part */ + const float beta, /* i : forgetting factor for average filtering */ + const int16_t *band_grouping, /* i : indices of band groups */ + const int16_t N_bands, /* i : number of bands (groups) */ + const int16_t enc_param_start_band, /* i : first band to process */ + float *azi, /* o : array of sector azimuth angles, flat */ + float *ele, /* o : array of sector elevation angles, flat */ + float *diff, /* o : array of sector diffuseness values, flat */ + float *ene /* o : array of sector energy values, flat */ ); void ivas_mc_paramupmix_enc( - Encoder_Struct *st_ivas, /* i/o: IVAS Encoder handle */ - BSTR_ENC_HANDLE hMetaData, /* i/o: IVAS Metadata bitstream handle */ + Encoder_Struct *st_ivas, /* i/o: IVAS Encoder handle */ + BSTR_ENC_HANDLE hMetaData, /* i/o: IVAS Metadata bitstream handle */ float data_f[][L_FRAME48k], /* i/o: input: MC data */ - const int16_t input_frame /* i : input frame length */ + const int16_t input_frame /* i : input frame length */ ); ivas_error ivas_mc_paramupmix_enc_open( - Encoder_Struct *st_ivas /* i/o: IVAS encoder handle */ + Encoder_Struct *st_ivas /* i/o: IVAS encoder handle */ ); void ivas_mc_paramupmix_enc_close( - MC_PARAMUPMIX_ENC_HANDLE *hMCParamUpmix, /* i/o: MC Param-Upmix encoder handle */ + MC_PARAMUPMIX_ENC_HANDLE *hMCParamUpmix, /* i/o: MC Param-Upmix encoder handle */ const int32_t input_Fs /* i : input sampling rate */ ); void ivas_mc_paramupmix_dec( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ - float output_f[][L_FRAME48k] /* i/o: synthesized core-coder transport channels/DirAC output */ + Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ + float output_f[][L_FRAME48k] /* i/o: synthesized core-coder transport channels/DirAC output */ ); ivas_error ivas_mc_paramupmix_dec_open( - Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ + Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ ); void ivas_mc_paramupmix_dec_close( - MC_PARAMUPMIX_DEC_HANDLE *hMCParamUpmix_out /* i/o: Parametric MC decoder handle */ + MC_PARAMUPMIX_DEC_HANDLE *hMCParamUpmix_out /* i/o: Parametric MC decoder handle */ ); void ivas_mc_paramupmix_dec_read_BS( Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ - Decoder_State *st, /* i/o: decoder state structure */ - MC_PARAMUPMIX_DEC_HANDLE hMCParamUpmix, /* i/o: decoder MC Param-Upmix handle */ - int16_t *nb_bits /* o : number of bits written */ + Decoder_State *st, /* i/o: decoder state structure */ + MC_PARAMUPMIX_DEC_HANDLE hMCParamUpmix, /* i/o: decoder MC Param-Upmix handle */ + int16_t *nb_bits /* o : number of bits written */ ); #ifdef JBM_PARAMUPMIX @@ -3809,7 +4019,7 @@ void ivas_param_mc_dec_read_BS( void ivas_param_mc_dec_digest_tc( Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ - const uint8_t nCldfbSlots, /* i : number of CLFBS slots in the transport channels */ + const uint8_t nCldfbSlots, /* i : number of CLFBS slots in the transport channels */ float *transport_channels_f[] /* i : synthesized core-coder transport channels/DirAC output*/ ); @@ -4459,7 +4669,7 @@ void ivas_spar_to_dirac( ivas_spar_md_dec_state_t *hMdDec, /* i/o: SPAR MD decoder handle */ const int16_t dtx_vad, /* i : DTX frame flag */ const int16_t num_bands_out, /* i : number of output bands */ - const int16_t bw /* i : band joining factor */ + const int16_t bw /* i : band joining factor */ ); void ivas_spar_update_md_hist( @@ -4469,13 +4679,13 @@ void ivas_spar_update_md_hist( void ivas_spar_smooth_md_dtx( ivas_spar_md_dec_state_t *hMdDec, /* i/o: SPAR MD decoder handle */ const int16_t num_bands_out, /* i : number of output bands */ - const int16_t num_md_sub_frames /* i : number of metadata subframes */ + const int16_t num_md_sub_frames /* i : number of metadata subframes */ ); void ivas_spar_setup_md_smoothing( ivas_spar_md_dec_state_t *hMdDec, /* i/o: SPAR MD decoder handle */ const int16_t num_bands_out, /* i : number of output bands */ - const int16_t num_md_sub_frames /* i : number of metadata subframes */ + const int16_t num_md_sub_frames /* i : number of metadata subframes */ ); void ivas_spar_dec_gen_umx_mat( @@ -4553,7 +4763,7 @@ void ivas_transient_det_close( void ivas_transient_det_process( ivas_trans_det_state_t *hTranDet, /* i/o: SPAR TD handle */ float *pIn_pcm, /* i : input audio channels */ - const int16_t frame_len, /* i : frame length in samples */ + const int16_t frame_len, /* i : frame length in samples */ int16_t transient_det[2] /* o : transient det outputs */ ); @@ -4744,15 +4954,14 @@ void ivas_spar_arith_coeffs_com_init( ); int16_t ivas_arith_encode_cmplx_cell_array( - - ivas_arith_t *pArith_re, - ivas_arith_t *pArith_re_diff, - const int16_t *pDo_diff, - const int16_t nB, - int16_t *pSymbol_re, - int16_t *pSymbol_old_re, - ivas_cell_dim_t *pCell_dims, - BSTR_ENC_HANDLE hMetaData, + ivas_arith_t *pArith_re, + ivas_arith_t *pArith_re_diff, + const int16_t *pDo_diff, + const int16_t nB, + int16_t *pSymbol_re, + int16_t *pSymbol_old_re, + ivas_cell_dim_t *pCell_dims, + BSTR_ENC_HANDLE hMetaData, const int16_t any_diff , const int16_t wc_strat_arith ); @@ -4905,7 +5114,7 @@ ivas_error ivas_masa_enc_open( ); void ivas_masa_enc_close( - MASA_ENCODER_HANDLE *hMasa /* i/o: MASA metadata structure */ + MASA_ENCODER_HANDLE *hMasa /* i/o: MASA metadata structure */ ); void ivas_masa_enc_reconfigure( @@ -4926,6 +5135,16 @@ ivas_error ivas_masa_encode( const int32_t ivas_total_brate, /* i : IVAS total bitrate */ const int16_t Opt_DTX_ON, /* i : DTX on flag */ const int16_t element_mode /* i : element mode */ +#ifdef MASA_AND_OBJECTS + , + const ISM_MODE ism_mode, /* i : ISM format mode */ + const int16_t nchan_ism, /* i : number of ISM channels */ + ISM_METADATA_HANDLE hIsmMetaData[MAX_NUM_OBJECTS], /* i : ISM metadata handle */ + const int16_t idx_separated_object, /* i : index of the separated object */ + OMASA_ENC_HANDLE hOMasa, /* i : OMASA encoder handle */ + const int16_t ism_imp, /* i : importance of separated object */ + const int16_t flag_omasa_ener_brate /* i : less bitrate for objects in OMASA flag */ +#endif ); void ivas_masa_estimate_energy( @@ -4940,19 +5159,109 @@ ivas_error ivas_masa_enc_config( ); void ivas_masa_set_elements( - const int32_t ivas_total_brate, /* i : codec total bitrate */ + const int32_t ivas_total_brate, /* i : IVAS total bitrate */ const int16_t mc_mode, /* i : MC format mode */ const int16_t nchan_transport, /* i : number of MASA input/transport channels */ IVAS_QMETADATA_HANDLE hQMetaData, /* i/o: q_metadata handle */ int16_t *element_mode, /* o : element mode */ int16_t *nSCE, /* o : number of SCEs */ int16_t *nCPE /* o : number of CPEs */ +#ifdef MASA_AND_OBJECTS + , + const int16_t ivas_format, /* i : IVAS format */ + const ISM_MODE ism_mode, /* i : ISM mode */ + const int32_t ism_total_brate /* i : initial ISM total bitrate */ +#endif +); + +#ifdef MASA_AND_OBJECTS +/*! r: valid or not 1/0 */ +int16_t valid_ratio_index( + int16_t index, /* i : index to be checked */ + const int16_t K, /* i : L1 norm to check against */ + const int16_t len /* i : vector length */ +); + +void reconstruct_ism_ratios( + int16_t *ratio_ism_idx, + const int16_t nchan_ism, + const float step, + float *q_energy_ratio_ism +); + +void distribute_evenly_ism( + int16_t *idx, + const int16_t K, + const int16_t nchan_ism +); + +int16_t ivas_qmetadata_DecodeExtendedGR( + uint16_t* bitstream, + int16_t* index, + const int16_t alph_size, + const int16_t gr_param +); + +int16_t ivas_qmetadata_encode_extended_gr_length( + const uint16_t value, + const uint16_t alphabet_size, + const int16_t gr_param); + +void ivas_qmetadata_encode_extended_gr( + BSTR_ENC_HANDLE hMetaData, /* i/o: q_metadata handle */ + const uint16_t value, /* i : value to be encoded */ + const uint16_t alphabet_size, /* i : alphabet size */ + const int16_t gr_param); /* i : GR order */ + +/*! r: CPE bitrate value */ +int32_t calculate_cpe_brate_MASA_ISM( + const ISM_MODE ism_mode, /* i : ism mode */ + const int32_t ivas_total_brate, /* i : IVAS total bitrate */ + const int16_t nchan_ism /* i : number of objects */ +); + +void ivas_merge_masa_metadata( + MASA_ENCODER_HANDLE hMasa, /* i/o: MASA enc handle. source for MASA metadata and combined metadata will be here */ + OMASA_SPATIAL_META_HANDLE hOMasaMeta /* i : ISM-object metadata to be merged with the MASA metadata */ +); + +void ivas_masa_combine_directions( + MASA_ENCODER_HANDLE hMasa /* i/o: MASA encoder handle */ +); + +/*!r : number of bits for ISM ratio index */ +int16_t bits_index_ism_ratio( + const int16_t nchan_ism /* i : number of objects */ +); + +void calculate_nbits_meta( + const int16_t nchan_ism, + float q_energy_ratio_ism[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS], + float masa_to_total_energy_ratio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], + const int16_t numSf, + const int16_t numCodingBands, + int16_t* bits_ism, + const int16_t idx_sep_obj, + const int16_t ism_imp +); + +/*! r: limitation flag */ +int16_t calculate_brate_limit_flag( + const int16_t ism_imp[], /* i : ISM importance flags */ + const int16_t nchan_ism /* i : number of objects */ ); +void ivas_get_stereo_panning_gains( + const float aziDeg, + const float eleDeg, + float panningGains[2] +); +#endif + void ivas_masa_set_coding_config( MASA_CODEC_CONFIG* config, /* i/o: MASA coding config structure */ int16_t* band_mapping, /* o : Band mapping used */ - const int32_t ivas_total_brate, /* i : codec total bitrate */ + const int32_t ivas_total_brate, /* i : IVAS total bitrate */ const int16_t nchan_transport, /* i : number of transport channel (mono/stereo) */ const uint8_t isMcMasa /* i : toggle for selecting McMASA specific config */ ); @@ -5020,7 +5329,6 @@ void ivas_masa_prerender( #endif ); - void ivas_spar_param_to_masa_param_mapping( Decoder_Struct *st_ivas, /* i/o: IVAS decoder struct */ float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* i : Input audio in CLDFB domain, real */ @@ -5171,6 +5479,10 @@ ivas_error vbap_init_data( const float *speaker_node_azi_deg, /* i : vector of speaker node azimuths (positive left) */ const float *speaker_node_ele_deg, /* i : vector of speaker node elevations (positive up) */ const int16_t num_speaker_nodes /* i : number of speaker nodes in the set */ +#ifdef MASA_AND_OBJECTS + , + const IVAS_FORMAT ivas_format /* i : IVAS format */ +#endif ); void vbap_free_data( @@ -5182,6 +5494,10 @@ void vbap_determine_gains( float *gains, /* o : gain vector for speaker nodes for given direction */ const int16_t azi_deg, /* i : azimuth in degrees for panning direction (positive left) */ const int16_t ele_deg /* i : elevation in degrees for panning direction (positive up) */ +#ifdef MASA_AND_OBJECTS + , + const int16_t use_object_mode /* i : select between object mode panning and spatial mode panning */ +#endif ); void v_sort_ind( @@ -5283,7 +5599,7 @@ void ivas_mcmasa_set_separate_channel_mode( void ivas_mcmasa_split_brate( const uint8_t separateChannelEnabled, /* i : Transport running in "separate channel" mode */ - const int32_t ivas_total_brate, /* i : Total bitrate available to be split */ + const int32_t ivas_total_brate, /* i : IVAS total bitrate available to be split */ const int16_t nSCE, /* i : Number of SCEs in use (0 or 1) */ const int16_t nCPE, /* i : Number of CPEs in use (0 or 1) */ int32_t *brate_sce, /* o : Pointer to SCE element bitrate */ @@ -5372,6 +5688,7 @@ void ivas_lfe_synth_with_filters( ); +#ifdef FIX_572_LFE_LPF_ENC /*----------------------------------------------------------------------------------* * LFE encoder low pass filter prototypes *----------------------------------------------------------------------------------*/ @@ -5390,6 +5707,7 @@ void ivas_lfe_lpf_enc_apply( float data_lfe_ch[], /* i/o: LFE signal */ const int16_t input_frame /* i : input frame length per channel */ ); +#endif /*----------------------------------------------------------------------------------* @@ -5462,6 +5780,189 @@ void ivas_filter_process( ); +#ifdef MASA_AND_OBJECTS +/*----------------------------------------------------------------------------------* +* OMASA prototypes +*---------------------------------------------------------------------------------*/ + +ivas_error ivas_omasa_enc_open( + Encoder_Struct* st_ivas /* i/o: IVAS encoder handle */ +); + +void ivas_omasa_enc_close( + OMASA_ENC_HANDLE *hOMasa /* i/o: encoder OMASA handle */ +); + +ivas_error ivas_omasa_enc_config( + Encoder_Struct *st_ivas /* i/o: IVAS encoder structure */ +); + +ivas_error ivas_omasa_dec_config( + Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ +); + +void ivas_omasa_set_config( + OMASA_ENC_HANDLE hOMasa, /* i/o: OMASA encoder handle */ + MASA_ENCODER_HANDLE hMasa, /* i : MASA encoder handle */ + const int32_t input_Fs, /* i : Input sample rate */ + const ISM_MODE ism_mode /* i : ISM mode */ +); + +void ivas_omasa_enc( + OMASA_ENC_HANDLE hOMasa, /* i/o: OMASA encoder handle */ + MASA_ENCODER_HANDLE hMasa, /* i/o: MASA encoder handle */ + ISM_METADATA_HANDLE hIsmMeta[], /* i/o: ISM metadata handle */ + float data_in_f[][L_FRAME48k], /* i/o: Input / transport audio signals */ + const int16_t input_frame, /* i : Input frame size */ + const int16_t nchan_transport, /* i : Number of transport channels */ + const int16_t nchan_ism, /* i : Number of objects for parameter analysis*/ + const ISM_MODE ism_mode, /* i : ISM mode */ + float data_separated_object[L_FRAME48k], /* o : Separated object audio signal */ + int16_t* idx_separated_object /* o : Index of the separated object */ +); + +void ivas_set_surplus_brate_enc( + Encoder_Struct *st_ivas /* i/o: IVAS encoder structure */ +#ifdef DEBUG_MODE_INFO + , + const int16_t *nb_bits_metadata /* i : number of metadata bits */ +#endif +); + +void ivas_set_surplus_brate_dec( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + int32_t *ism_total_brate /* i : ISM total bitrate */ +); + +void set_ism_importance_interformat( + const int32_t ism_total_brate, /* i/o: ISms total bitrate */ + const int16_t nchan_transport, /* i : number of transported channels */ + ISM_METADATA_HANDLE hIsmMeta[], /* i/o: ISM metadata handles */ + SCE_ENC_HANDLE hSCE[], /* i/o: SCE encoder handles */ + const float lp_noise_CPE, /* i : LP filtered total noise estimation */ + int16_t ism_imp[] /* o : ISM importance flags */ +); + +#ifdef MASA_AND_OBJECTS +/*! r: flag for using less bitrate for objects in OMASA */ +int16_t ivas_omasa_ener_brate( + const int16_t nchan_ism, /* i : number of ISMs */ + const int32_t ivas_total_brate, /* i : IVAS total bitrate */ + float data_f[][L_FRAME48k], /* i : Input / transport audio signals */ + const int16_t input_frame /* i : Input frame size */ +); +#endif + +/*! r: adjusted bitrate */ +int32_t ivas_interformat_brate( + const ISM_MODE ism_mode, /* i : ISM mode */ + const int16_t nchan_ism, /* i : number of ISM channels */ + const int32_t element_brate, /* i : element bitrate */ + const int16_t ism_imp, /* i : ISM importance flag */ + const int16_t limit_flag /* i : flag to limit the bitrate increase */ +); + +void ivas_combined_format_brate_sanity( + const int32_t element_brate, /* i : element bitrate */ + const int16_t core, /* i : core */ + int32_t *core_brate, /* i/o: core bitrate */ + int16_t *diff_nBits /* o : number of differential bits */ +); + +ISM_MODE ivas_omasa_ism_mode_select( + const int32_t ivas_total_brate, /* i : IVAS total bitrate */ + const int16_t nchan_ism /* i : number of input ISM's */ +); + +void ivas_set_omasa_TC( + const ISM_MODE ism_mode, /* i : ISM mode */ + const int16_t nchan_ism, /* i : number of input ISMs */ + int16_t *nSCE, /* o : number of SCEs */ + int16_t *nCPE /* o : number of CPEs */ +); + +void ivas_merge_masa_transports( + float data_in_f1[][L_FRAME48k], /* i : Transport audio signals 1 */ + float data_in_f2[][L_FRAME48k], /* i : Transport audio signals 2 */ + float data_out_f[][L_FRAME48k], /* o : Merged transport audio signals */ + const int16_t input_frame, /* i : Input frame size */ + const int16_t num_transport_channels /* i : Number of transport audio signals */ +); + +ivas_error ivas_masa_ism_data_open( + Decoder_Struct* st_ivas /* i/o: IVAS decoder handle */ +); + +void ivas_masa_ism_data_close( + MASA_ISM_DATA_HANDLE *hMasaIsmData /* i/o: MASA_ISM rendering handle */ +); + +ivas_error ivas_omasa_ism_metadata_dec( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const int32_t ism_total_brate, /* i : ISM total bitrate */ + int16_t *nchan_ism, /* o : number of ISM separated channels */ + int16_t *nchan_transport_ism, /* o : number of ISM TCs */ + const int16_t dirac_bs_md_write_idx, /* i : DirAC bitstream write index */ + int16_t nb_bits_metadata[] /* o : number of ISM metadata bits */ +); + +ivas_error ivas_omasa_dirac_td_binaural( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + float output[][L_FRAME48k], /* o : output synthesis signal */ + const int16_t output_frame /* i : output frame length per channel */ +); + +void ivas_omasa_dirac_rend( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + float output[][L_FRAME48k], /* o : output synthesis signal */ + const int16_t output_frame /* i : output frame length per channel */ +); + +void preProcessStereoTransportsForMovedObjects( + Decoder_Struct* st_ivas, + float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], + float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], + const int16_t nBins, + const int16_t subframe +); + +ivas_error ivas_masa_ism_separate_object_renderer_open( + Decoder_Struct* st_ivas /* i/o: IVAS decoder structure */ +); + +void ivas_masa_ism_separate_object_render( + Decoder_Struct* st_ivas, /* i/o: IVAS decoder structure */ + float input_f[][L_FRAME48k], /* i : separated object signal */ + float output_f[][L_FRAME48k], /* i/o: output signals */ + const int16_t output_frame /* i : output frame length per channel */ +); + +void ivas_masa_ism_set_edited_objects( + Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ +); + +void encode_masa_to_total( + IVAS_QMETADATA_HANDLE hQMetaData, + BSTR_ENC_HANDLE hMetaData, + const int16_t low_bitrate_mode, + const int16_t nbands, + const int16_t nblocks +); + +void decode_masa_to_total( + uint16_t* bit_stream, + int16_t* index, + float masa_to_total_energy_ratio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], + const int16_t nbands, + const int16_t nblocks +); + +void modify_masa_energy_ratios( + IVAS_QMETADATA_HANDLE hQMetaData +); + +#endif + /*----------------------------------------------------------------------------------* * TD Binaural Object renderer *----------------------------------------------------------------------------------*/ diff --git a/lib_com/ivas_rom_com.c b/lib_com/ivas_rom_com.c index 5677a3cc9b48b95616b71944fc1583ce2ae16e89..a131509ea1ec18c18630518f7a4835e4fd276685 100644 --- a/lib_com/ivas_rom_com.c +++ b/lib_com/ivas_rom_com.c @@ -2824,6 +2824,75 @@ const float McMASA_LFEGain_vectors[64] = -2.14f, 0.26f, 0.84f, 1.02f }; +#ifdef MASA_AND_OBJECTS +/*----------------------------------------------------------------------------------* + * OMASA ROM tables + *----------------------------------------------------------------------------------*/ + +const int32_t sep_object_brate[][MAX_NUM_OBJECTS] = +{ + {0, 0, 0, 0}, /* 13k2 */ + {0, 0, 0, 0}, /* 16k4 */ + {9600, 0, 0, 0}, /* 24k4 */ + {IVAS_13k2, 0, 0, 0}, /* 32k */ + {16000, 11000, 0, 0}, /* 48k */ + {16000, 11700, 0, 0}, /* 64k */ + {20000, 16000, 0, 0}, /* 80k */ + {IVAS_32k, 20000, 20000, 0}, /* 96k */ + {IVAS_32k, IVAS_24k4, 24000, 24000}, /* 128k */ + {IVAS_48k, IVAS_32k, IVAS_24k4, 24000}, /* 160k */ + {IVAS_64k, IVAS_48k, IVAS_32k, IVAS_24k4}, /* 192k */ + {IVAS_96k, IVAS_64k, IVAS_48k, IVAS_32k}, /* 256k */ + {IVAS_128k, IVAS_80k, IVAS_64k, IVAS_48k}, /* 384k */ + {IVAS_128k, IVAS_96k, IVAS_80k, IVAS_64k} /* 512k */ +}; + +/* column wise DCT matrices for 4 5, and 8 dim */ +const float dct4[4*4] = +{ + 0.5000f, 0.6533f, 0.5000f, 0.2706f, + 0.5000f, 0.2706f, -0.5000f, -0.6533f, + 0.5000f, -0.2706f, -0.5000f, 0.6533f, + 0.5000f, -0.6533f, 0.5000f, -0.2706f +}; + +const float dct5[5*5] = +{ + 0.4472f, 0.6015f, 0.5117f, 0.3717f, 0.1954f, + 0.4472f, 0.3717f, -0.1954f, -0.6015f, -0.5117f, + 0.4472f, 0.0000f, -0.6325f, -0.0000f, 0.6325f, + 0.4472f, -0.3717f, -0.1954f, 0.6015f, -0.5117f, + 0.4472f, -0.6015f, 0.5117f, -0.3717f, 0.1954f +}; + +const float dct8[8*8] = +{ + 0.3536f, 0.4904f, 0.4619f, 0.4157f, 0.3536f, 0.2778f, 0.1913f, 0.0975f, + 0.3536f, 0.4157f, 0.1913f, -0.0975f, -0.3536f, -0.4904f, -0.4619f, -0.2778f, + 0.3536f, 0.2778f, -0.1913f, -0.4904f, -0.3536f, 0.0975f, 0.4619f, 0.4157f, + 0.3536f, 0.0975f, -0.4619f, -0.2778f, 0.3536f, 0.4157f, -0.1913f, -0.4904f, + 0.3536f, -0.0975f, -0.4619f, 0.2778f, 0.3536f, -0.4157f, -0.1913f, 0.4904f, + 0.3536f, -0.2778f, -0.1913f, 0.4904f, -0.3536f, -0.0975f, 0.4619f, -0.4157f, + 0.3536f, -0.4157f, 0.1913f, 0.0975f, -0.3536f, 0.4904f, -0.4619f, 0.2778f, + 0.3536f, -0.4904f, 0.4619f, -0.4157f, 0.3536f, -0.2778f, 0.1913f, -0.0975f +}; + +const float dct12[12*12]= +{ + 0.2887f, 0.4048f, 0.3943f, 0.3772f, 0.3536f, 0.3239f, 0.2887f, 0.2485f, 0.2041f, 0.1562f, 0.1057f, 0.0533f, + 0.2887f, 0.3772f, 0.2887f, 0.1562f, 0.0000f, -0.1562f, -0.2887f, -0.3772f, -0.4082f, -0.3772f, -0.2887f, -0.1562f, + 0.2887f, 0.3239f, 0.1057f, -0.1562f, -0.3536f, -0.4048f, -0.2887f, -0.0533f, 0.2041f, 0.3772f, 0.3943f, 0.2485f, + 0.2887f, 0.2485f, -0.1057f, -0.3772f, -0.3536f, -0.0533f, 0.2887f, 0.4048f, 0.2041f, -0.1562f, -0.3943f, -0.3239f, + 0.2887f, 0.1562f, -0.2887f, -0.3772f, -0.0000f, 0.3772f, 0.2887f, -0.1562f, -0.4082f, -0.1562f, 0.2887f, 0.3772f, + 0.2887f, 0.0533f, -0.3943f, -0.1562f, 0.3536f, 0.2485f, -0.2887f, -0.3239f, 0.2041f, 0.3772f, -0.1057f, -0.4048f, + 0.2887f, -0.0533f, -0.3943f, 0.1562f, 0.3536f, -0.2485f, -0.2887f, 0.3239f, 0.2041f, -0.3772f, -0.1057f, 0.4048f, + 0.2887f, -0.1562f, -0.2887f, 0.3772f, 0.0000f, -0.3772f, 0.2887f, 0.1562f, -0.4082f, 0.1562f, 0.2887f, -0.3772f, + 0.2887f, -0.2485f, -0.1057f, 0.3772f, -0.3536f, 0.0533f, 0.2887f, -0.4048f, 0.2041f, 0.1562f, -0.3943f, 0.3239f, + 0.2887f, -0.3239f, 0.1057f, 0.1562f, -0.3536f, 0.4048f, -0.2887f, 0.0533f, 0.2041f, -0.3772f, 0.3943f, -0.2485f, + 0.2887f, -0.3772f, 0.2887f, -0.1562f, -0.0000f, 0.1562f, -0.2887f, 0.3772f, -0.4082f, 0.3772f, -0.2887f, 0.1562f, + 0.2887f, -0.4048f, 0.3943f, -0.3772f, 0.3536f, -0.3239f, 0.2887f, -0.2485f, 0.2041f, -0.1562f, 0.1057f, -0.0533f +}; +#endif /*----------------------------------------------------------------------------------* * ISM ROM tables diff --git a/lib_com/ivas_rom_com.h b/lib_com/ivas_rom_com.h index 8dc958e06c9a0e3ff3c3c37add4c722a0a719888..15fbd2048d8219f892126733b72b603a2e16418c 100644 --- a/lib_com/ivas_rom_com.h +++ b/lib_com/ivas_rom_com.h @@ -260,7 +260,6 @@ extern const uint16_t ivas_param_mc_sym_freq_icc_combined_48_16bits[PARAM_MC_SZ_ extern const uint16_t ivas_param_mc_cum_freq_icc_delta_combined_48_16bits[2 * PARAM_MC_SZ_ICC_QUANTIZER]; extern const uint16_t ivas_param_mc_sym_freq_icc_delta_combined_48_16bits[2 * PARAM_MC_SZ_ICC_QUANTIZER - 1]; - /*----------------------------------------------------------------------------------* * Parametric Upmix MC ROM tables *----------------------------------------------------------------------------------*/ @@ -326,6 +325,18 @@ extern const float cb_azi_chan[]; extern const float McMASA_LFEGain_vectors[64]; +#ifdef MASA_AND_OBJECTS +/*----------------------------------------------------------------------------------* + * MASA and ISM (OMASA) combined format ROM tables + *----------------------------------------------------------------------------------*/ + +extern const int32_t sep_object_brate[][MAX_NUM_OBJECTS]; +extern const float dct4[]; +extern const float dct5[]; +extern const float dct8[]; +extern const float dct12[]; +#endif + /*----------------------------------------------------------------------------------* * ISM ROM tables *----------------------------------------------------------------------------------*/ @@ -339,7 +350,6 @@ extern const float ism_elevation_borders[4]; extern const int16_t Param_ISM_band_grouping[MAX_PARAM_ISM_NBANDS + 1]; - /*----------------------------------------------------------------------------------* * LFE coding ROM tables *----------------------------------------------------------------------------------*/ diff --git a/lib_com/ivas_stat_com.h b/lib_com/ivas_stat_com.h index 6d2ed4c4e961dc316964a7b9b0791d6e88a32456..46c58b9bb2b3e0e56e2fbd6ede7edf8b239e66cc 100644 --- a/lib_com/ivas_stat_com.h +++ b/lib_com/ivas_stat_com.h @@ -81,6 +81,14 @@ typedef struct int16_t ism_md_inc_diff_cnt; /* counter of continuous frames where MD are transmitted in inactive segments when MD significantly changes */ float last_true_radius; /* last true Q radius value */ +#ifdef MASA_AND_OBJECTS + int16_t ism_imp; /* ISM importance flag */ + int16_t ism_md_null_flag; + int16_t ism_md_lowrate_flag; + float q_azimuth_old; + float q_elevation_old; +#endif + } ISM_METADATA_FRAME, *ISM_METADATA_HANDLE; @@ -169,8 +177,10 @@ typedef struct ivas_param_ism_data_structure int16_t noisy_speech_buffer[PARAM_ISM_HYS_BUF_SIZE]; int16_t flag_equal_energy; +#ifdef FIX_549_DMX_GAIN float last_dmx_gain; float last_cardioid_left[MAX_NUM_OBJECTS]; +#endif } PARAM_ISM_CONFIG_DATA, *PARAM_ISM_CONFIG_HANDLE; @@ -442,6 +452,16 @@ typedef struct ivas_masa_common_spatial_meta_struct } MASA_COMMON_SPATIAL_META; +#ifdef MASA_AND_OBJECTS +typedef struct ivas_omasa_meta_struct +{ + uint8_t num_dirs; + MASA_DIRECTIONAL_SPATIAL_META directional_meta[MASA_MAXIMUM_DIRECTIONS]; + MASA_COMMON_SPATIAL_META common_meta; + +} OMASA_SPATIAL_META, *OMASA_SPATIAL_META_HANDLE; +#endif + typedef struct ivas_masa_metadata_frame_struct { MASA_DECRIPTIVE_META descriptive_meta; @@ -551,6 +571,9 @@ typedef struct ivas_masa_qmetadata_frame_struct int16_t ec_flag; float dir_comp_ratio; uint8_t is_masa_ivas_format; +#ifdef MASA_AND_OBJECTS + float masa_to_total_energy_ratio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; /* TODO Nokia: This should be moved to some other place and reserved only when needed. */ +#endif } IVAS_QMETADATA, *IVAS_QMETADATA_HANDLE; diff --git a/lib_com/ivas_stereo_td_bit_alloc.c b/lib_com/ivas_stereo_td_bit_alloc.c index dee56c5dff17f6b34fb245fcf8beb729603e6b09..823c1b194458b3fcc6cf4c424997ed104b3b3250 100644 --- a/lib_com/ivas_stereo_td_bit_alloc.c +++ b/lib_com/ivas_stereo_td_bit_alloc.c @@ -74,6 +74,10 @@ *-------------------------------------------------------------------*/ void tdm_bit_alloc( +#ifdef MASA_AND_OBJECTS + const int16_t ivas_format, /* i : IVAS format */ + const int16_t ism_mode, /* i: ISM mode in combined format */ +#endif const int32_t element_brate_wo_meta, /* i : element bitrate without metadata */ const int16_t tdm_lp_reuse_flag, /* i : LPC reusage flag */ int32_t *total_brate_pri, /* o : Allocated primary channel bitrate */ @@ -136,7 +140,11 @@ void tdm_bit_alloc( *total_brate_sec = tdm_bit_allc_tbl[idx][coder_type]; /* secondary channel bitrate allocation based on the energy scaling ratio */ +#ifdef MASA_AND_OBJECTS + if ( ( ( ivas_format != MASA_ISM_FORMAT || ism_mode == ISM_MODE_NONE ) && ( ( coder_type != UNVOICED ) || tdm_LRTD_flag == 1 ) ) || ( ivas_format == MASA_ISM_FORMAT && ism_mode != ISM_MODE_NONE && coder_type > UNVOICED ) ) +#else if ( ( coder_type != UNVOICED ) || tdm_LRTD_flag == 1 ) +#endif { bit_rate_diff = (float) ( element_brate_wo_meta - 2 * *total_brate_sec ); @@ -416,7 +424,6 @@ void tdm_bit_alloc( *total_brate_sec += 100; } } - *total_brate_pri = element_brate_wo_meta - *total_brate_sec; return; diff --git a/lib_com/options.h b/lib_com/options.h index b56d19f88d185996beb195a28f31bb0f52c12b87..1b47d0dd5cfabf5d8a5a9430f50e04962edb12e1 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -153,22 +153,41 @@ #define VLBR_20MS_MD /* Dlb: SBA VLBR 20ms Optimization*/ #define SBA_MODE_CLEANUP_2 /* Dlb : changes part of fix issue #523 for unused signaling bit in SBA SID*/ #define FIX_137_SID_MD_BITS /* Dlb: Fix issue #137 , SID bitrate mismatch correction */ +#define FIX_563_PARAMMC_LIMITER /* FhG: issue 563: fix ILD limiter when coming from silence w/o transient set */ +#define FIX_560_VAD_FLAG /* Eri: Issue 560 - VAD flag issue for unified stereo */ +#define FIX_549_DMX_GAIN /* FhG: issue 549: ParamISM output too quiet */ #define FIX_470_MASA_JBM_EXT /* Nokia: Issue 470, fix MASA EXT output with JBM */ +#define ISM_FB /* issue 556: change SWB to FB coding in 1ISM at 24.4 kbps */ +#define FIX_558_PLC_DISCONT /* FhG: issue 558: fix discontinuities in DFT Stereo when switching from TCX concealment to ACELP */ #define FIX_564 /* Nokia: Issue 564: Fix gains in JBM path for SBA with parametric binaural renderer */ +#define FIX_566_2DIR_MASA_384K /* Nokia: Issued 566: Bugfix in 384k MASA metadata encoding of second direction */ +#define FIX_568_ISM_BITRATE_SWITCHING /* Philips: Issue 568: Bugfix for renderer re-initialization by ISM and bitrate switching */ +#define FIX_565_SBA_BURST_IN_FEC /* VA: Issue 565: Fix noise burst during FEC, due to wrong total_brate initialization */ +#define FIX_562_ISM2_64KBPS /* VA: issue 562: fix ISM2 at 64kbps issue */ #define FIX_559_EXTL_IGF_MISMATCH /* VA: issue 559: fix mismatch between st->extl and st->igf observed as crash in PlanarSBA bitrate switching */ #define FIX_571_REVERB_NOT_ACTIVATED_ISM /* Philips: Issue 571: Reverb not activated for discrete and parametric ISM */ +#define FIX_572_LFE_LPF_ENC /* FhG: issue 572: always apply the low pass filter to the LFE channel */ #define FIX_QMETA_SID_5k2 /* Nokia: Issue 137: enable using full 5.2k bitrate in MASA SID */ +#define FIX_578_PARAMMC_ILD_BS /* FhG: Issue 578: transmitt also center ILD in band 0 when LFE is active in 3TC ParamMC */ +#define FIX_UNCLR_ISSUE /* VoiceAge: issue 574: Fix UNCLR mis-classifications in noisy speech stereo */ +#define FIX_TCX_LOWRATE_LIMITATION /* VA: issue 577: TCX bitrate limitation only when DEBUGGING is active */ +#define FIX_575_LOW_OVERLAP_PLC_RECOVERY /* FhG: Issue 575 fix for PLC and transistion to TCX5*/ #define FIX_550_FIRST_FRAME_ACCESS /* Eri: Issue 550: TD Object renderer: first frame accesses wrong transport channel offsets */ #define FIX_550_FIRST_FRAME_ACCESS_ALT /* Eri: Issue 550: Should be merged with FIX_550_FIRST_FRAME_ACCESS above, or accepted at the same time */ #define FIX_569_TD_FILTER_LENGTH /* Eri: Issue 569: If an HRTF binary file exceeds the SFX_SPAT_BIN_MAX_FILTER_LENGTH the decoder crashes. This truncates the filter when generated from the model. */ +#define ISM_FB_16k4 /* VA: Issue: 579: change BW from SWB to FB in NxISM conditions to match the EVS codec */ +#define FIX_580_PARAMMC_ENER_BURSTS /* FhG: issue 580: energy bursts due to ILD holding when energy relations change too much */ #define FIX_595_SHL_NOGLOB /* FhG: Issue 595: compilation with BASOP_NOGLOB disabled */ #define UPDATE_FASTCONV_SBA_FILTER /* Dlb: Issue 584: Update SBA CLDFB-Domain HRTFs */ #define FIX_570_SF_EXT_ORIENTATION +#define FIX_593_STL_INCLUDE /* FhG: Issue 593: correct include of stl.h in lib_enc/ivas_stereo_eclvq_enc.c */ +#define FIX_583_CLANG_TRANS_DET /* FhG: Issue 583: clang left shift on ramp_up_flag in transient detector */ #define FIX_280_PLANAR_CP /* Dlb : fix issue 28 : remove planarCP=1 related code*/ #define CODE_CLEAN_UP_DIRAC /* Dlb : code clean up*/ #define COVARIANCE_MEMORY_OPT /* Dlb : Issue 231: define SPAR covariance buffers in stack instead of inter-frame heap */ #define NONBE_FIX_589_JBM_TC_OFFSETS /* FhG: issue 589: wrong offset into the TC buffers is used in some rendering paths in the JBM main rendering function */ #define FIX_MEM_REALLOC_IND_LIST /* VA: issue 601: failure of the automatic memory re-allocation mechanism when ind_list[] buffer is depleted in MASA mode with 2 TC*/ +#define FIX_581_CLANG_OFFSET_TO_NULL /* FhG: issue 581: fix CLANG error about applying an offset to a NULL pointer */ #define JBM_PARAMUPMIX /* Dlb: Issue 471: Integrate the Multichannel Parametric Upmix into the JBM path */ #define FIX_582_INDEX_OUT_OF_BOUNDS_SNS_AVQ_DEC /* FhG: fix an undefined behaviour error in SNS AVQ decoding */ #define FIX_614_ADD_TO_NULL_PTR_DIRAC_SETUP /* FhG: Issue 614: prevent adding to a null pointer in dirac setup code */ @@ -179,6 +198,9 @@ #define NONBE_FIX_539_MASA_384K_CHIRP /* Nokia: issue 539, puts the normalization of the energy ratios at the correct place, affect MASA 384k only */ /* Fixes for bugs found during split rendering contribution development */ +#define REND_STATIC_MEM_OPT /* Dlb: Static memory optimisation for external renderer */ +#define EULER2QUAT_FIX /* Dlb: Fix for Euler2Quat()/Quat2EulerDegree functions */ +#define SBA_CREND_ROT_OPT /* Dlb: Optimisation for rotateFrameSba() used for SHD rotations in external renderer */ #define TD_TDREND_FIX_NULLPTR_ACCESS /* FhG: avoid nullptr access in ivas_rend_TDObjRendOpen */ #define TD_REND_FIX_DIV_BY_ZERO /* FhG: avoid division by zero in sincResample fn */ #define RENAME_GWLPR /* FhG: Rename clashing symbol */ @@ -190,7 +212,15 @@ #define FIX_615_UBSAN_SPAR_TO_DIRAC /*Dlb : Fix for UBSAN issue 615*/ /* ################## End BE DEVELOPMENT switches ######################### */ - +#define MASA_AND_OBJECTS /* Nokia: Combination of MASA and objects */ +#ifdef MASA_AND_OBJECTS +#define MASAISM_EDIT_OBJECTS /* Nokia: Temporary command line editing of object directions in the decoder */ +#define FIX_356_ISM_METADATA_SYNC_OMASA // temp. fix +#define OMASA_BRSW_MONO_FIX /* Nokia: fix renderer config under rateswitching and MONO output */ +#define OMASA_FIX_LOW_FS /* Nokia: fixes related to lower input signal sampling rates */ +#define OMASA_BIT_BUFF_SZ /* Nokia: increase bitstream index buffer initial size */ +#define OMASA_EXT_OUTPUT /* VA: support of EXT output configuration for OMASA DISC mode */ +#endif /* #################### Start NON-BE CR switches ########################## */ /* any switch which is non-be wrt operation points tested in selection */ diff --git a/lib_dec/FEC.c b/lib_dec/FEC.c index 0a46a263cb79565695432cb97a6fe30ebddd9ace..2a49ff3b1fe9b50f286b1c23bd734bbb39a33bcd 100644 --- a/lib_dec/FEC.c +++ b/lib_dec/FEC.c @@ -331,7 +331,11 @@ void FEC_exc_estim( /*-----------------------------------------------------------------* * Replicate the last spectrum in case the last good frame was coded by GSC *-----------------------------------------------------------------*/ +#ifndef FIX_565_SBA_BURST_IN_FEC + if ( ( st->last_coder_type == AUDIO || st->last_good == INACTIVE_CLAS ) && st->total_brate <= ACELP_24k40 && !st->Opt_AMR_WB ) +#else if ( ( st->last_coder_type == AUDIO || st->last_good == INACTIVE_CLAS ) && st->total_brate <= MAX_GSC_INACTIVE_BRATE && !st->Opt_AMR_WB ) +#endif { /* Replication of the last spectrum, with a slight downscaling of its dynamic */ st->GSC_noisy_speech = st->Last_GSC_noisy_speech_flag; @@ -403,7 +407,11 @@ void FEC_exc_estim( /*-----------------------------------------------------------------* * Total excitation *-----------------------------------------------------------------*/ +#ifndef FIX_565_SBA_BURST_IN_FEC + if ( ( st->last_coder_type == AUDIO || st->last_good == INACTIVE_CLAS ) && st->total_brate <= ACELP_24k40 && !st->Opt_AMR_WB ) +#else if ( ( st->last_coder_type == AUDIO || st->last_good == INACTIVE_CLAS ) && st->total_brate <= MAX_GSC_INACTIVE_BRATE && !st->Opt_AMR_WB ) +#endif { /* For GSC - the excitation is already computed */ mvr2r( exc, exc2, st->L_frame ); diff --git a/lib_dec/dec_tcx.c b/lib_dec/dec_tcx.c index cffb6a1092ccf09839e6d7393126cb89a7ee3604..dd10cef29324326de7e73a828b35889ae317853a 100644 --- a/lib_dec/dec_tcx.c +++ b/lib_dec/dec_tcx.c @@ -377,7 +377,11 @@ void IMDCT( TCX_MDCT_Inverse( x + w * L_spec_TCX5, win, L_ola, L_win - L_ola, L_ola, st->element_mode ); } +#ifndef FIX_575_LOW_OVERLAP_PLC_RECOVERY + tcx_windowing_synthesis_current_frame( win, tcx_aldo_window_2, tcx_mdct_window_half, tcx_mdct_window_minimum, L_ola, tcx_mdct_window_half_length, tcx_mdct_window_min_length, ( w > 0 ) ? 0 : left_rect, ( w > 0 ) || ( w == 0 && index == 2 ) ? MIN_OVERLAP : hTcxCfg->tcx_last_overlap_mode, acelp_zir, hTcxDec->old_syn_Overl, syn_Overl_TDAC, st->old_Aq_12_8, tcx_mdct_window_trans, L_win, tcx_offset < 0 ? -tcx_offset : 0, ( w > 0 ) || ( frame_cnt > 0 ) ? 1 : st->last_core_bfi, ( w > 0 ) || ( frame_cnt > 0 ) ? 0 : st->last_is_cng, fullbandScale ); +#else tcx_windowing_synthesis_current_frame( win, tcx_aldo_window_2, tcx_mdct_window_half, tcx_mdct_window_minimum, L_ola, tcx_mdct_window_half_length, tcx_mdct_window_min_length, ( w > 0 ) ? 0 : left_rect, ( w > 0 ) || ( w == 0 && index == 2 ) ? MIN_OVERLAP : hTcxCfg->tcx_last_overlap_mode, acelp_zir, hTcxDec->old_syn_Overl, syn_Overl_TDAC, st->old_Aq_12_8, tcx_mdct_window_trans, L_win, tcx_offset < 0 ? -tcx_offset : 0, ( w > 0 ) || ( frame_cnt > 0 ) ? 1 : st->last_core, ( w > 0 ) || ( frame_cnt > 0 ) ? 0 : st->last_is_cng, fullbandScale ); +#endif if ( w > 0 ) { @@ -394,11 +398,13 @@ void IMDCT( /* To assure that no garbage values are passed to overlap */ set_zero( xn_buf + L_frame + tcx_offset + ( L_ola >> 1 ), overlap - tcx_offset - ( L_ola >> 1 ) ); +#ifdef FIX_575_LOW_OVERLAP_PLC_RECOVERY if ( st->prev_bfi && frame_cnt == 0 && st->last_core != st->last_core_bfi && st->last_core_bfi == ACELP_CORE ) { tcx_windowing_synthesis_past_frame( old_syn_overl, tcx_aldo_window_1_trunc, tcx_mdct_window_half, tcx_mdct_window_minimum, overlap, tcx_mdct_window_half_length, tcx_mdct_window_min_length, hTcxCfg->tcx_last_overlap_mode ); v_add( xn_buf, old_syn_overl, xn_buf, overlap ); } +#endif } else if ( !bfi && ( frame_cnt == 0 ) && ( hTcxCfg->tcx_curr_overlap_mode == FULL_OVERLAP ) ) @@ -1246,6 +1252,7 @@ void decoder_tcx_noisefilling( if ( ( frame_cnt == 0 ) && ( L_frameTCX == hTcxDec->L_frameTCX >> 1 ) && ( st->tcxonly ) && ( !st->tonal_mdct_plc_active ) && ( st->nbLostCmpt == 1 ) && ( hTcxCfg->tcx_last_overlap_mode != FULL_OVERLAP ) && ( hTcxCfg->tcx_curr_overlap_mode != FULL_OVERLAP ) ) { E_2ndlast = E_last = EPSILON; +#ifdef FIX_575_LOW_OVERLAP_PLC_RECOVERY if ( st->element_mode > EVS_MONO ) { for ( i = 0; i < L_frameTCX; i = i + 2 ) @@ -1262,11 +1269,19 @@ void decoder_tcx_noisefilling( E_last += st->hTonalMDCTConc->lastBlockData.spectralData[i + 1] * st->hTonalMDCTConc->lastBlockData.spectralData[i + 1]; } } +#else + for ( i = 0; i < infoIGFStartLine; i = i + 2 ) + { + E_2ndlast += st->hTonalMDCTConc->lastBlockData.spectralData[i] * st->hTonalMDCTConc->lastBlockData.spectralData[i]; + E_last += st->hTonalMDCTConc->lastBlockData.spectralData[i + 1] * st->hTonalMDCTConc->lastBlockData.spectralData[i + 1]; + } +#endif tmp2 = E_2ndlast / E_last; /* replace higher energy TCX5 frame by lower one to avoid energy fluctuation */ if ( tmp2 > 2 ) { +#ifdef FIX_575_LOW_OVERLAP_PLC_RECOVERY if ( st->element_mode > EVS_MONO ) { for ( i = 0; i < L_frameTCX; i = i + 2 ) @@ -1281,9 +1296,16 @@ void decoder_tcx_noisefilling( st->hTonalMDCTConc->lastBlockData.spectralData[i] = st->hTonalMDCTConc->lastBlockData.spectralData[i + 1]; } } +#else + for ( i = 0; i < infoIGFStartLine; i = i + 2 ) + { + st->hTonalMDCTConc->lastBlockData.spectralData[i] = st->hTonalMDCTConc->lastBlockData.spectralData[i + 1]; + } +#endif } else if ( tmp2 < 0.5 ) { +#ifdef FIX_575_LOW_OVERLAP_PLC_RECOVERY if ( st->element_mode > EVS_MONO ) { for ( i = 0; i < L_frameTCX; i = i + 2 ) @@ -1298,6 +1320,12 @@ void decoder_tcx_noisefilling( st->hTonalMDCTConc->lastBlockData.spectralData[i + 1] = st->hTonalMDCTConc->lastBlockData.spectralData[i]; } } +#else + for ( i = 0; i < infoIGFStartLine; i = i + 2 ) + { + st->hTonalMDCTConc->lastBlockData.spectralData[i + 1] = st->hTonalMDCTConc->lastBlockData.spectralData[i]; + } +#endif } } diff --git a/lib_dec/gs_dec.c b/lib_dec/gs_dec.c index 5ed7aa92c4b33f7212c99d5fa896876c43b6b8e6..1244f977936891d9b449612dd6e93023a71c4fdb 100644 --- a/lib_dec/gs_dec.c +++ b/lib_dec/gs_dec.c @@ -104,7 +104,11 @@ void decod_audio( } /* safety check in case of bit errors */ +#ifdef ISM_FB_16k4 if ( st->GSC_noisy_speech && st->bwidth < SWB && st->GSC_IVAS_mode == 0 ) +#else + if ( st->GSC_noisy_speech && st->bwidth != SWB && st->GSC_IVAS_mode == 0 ) +#endif { st->BER_detect = 1; st->GSC_noisy_speech = 0; diff --git a/lib_dec/ivas_core_dec.c b/lib_dec/ivas_core_dec.c index 0f644b1d6fb013ded9a28c07980d5b5832256ea0..bb0268e98010658765660826e3786b61fbc94331 100644 --- a/lib_dec/ivas_core_dec.c +++ b/lib_dec/ivas_core_dec.c @@ -274,6 +274,17 @@ ivas_error ivas_core_dec( } } +#ifdef MASA_AND_OBJECTS + /*------------------------------------------------------------------* + * Sanity check in combined format coding + *-----------------------------------------------------------------*/ + + if ( hCPE != NULL && hCPE->element_mode == IVAS_CPE_DFT && hCPE->brate_surplus > 0 ) + { + ivas_combined_format_brate_sanity( hCPE->element_brate, sts[0]->core, &( sts[0]->core_brate ), &tmps ); + } +#endif + /*------------------------------------------------------------------* * Core Decoding *-----------------------------------------------------------------*/ diff --git a/lib_dec/ivas_cpe_dec.c b/lib_dec/ivas_cpe_dec.c index 9096843e9c6c6b3fccdba1c51df0ff9ee7a368ad..365101b8bf7d4248d871f46047b9b67eb155c29e 100644 --- a/lib_dec/ivas_cpe_dec.c +++ b/lib_dec/ivas_cpe_dec.c @@ -52,6 +52,10 @@ static void read_stereo_mode_and_bwidth( CPE_DEC_HANDLE hCPE, const Decoder_Struct *st_ivas ); +#ifdef MASA_AND_OBJECTS +static void stereo_mode_combined_format_dec( const Decoder_Struct *st_ivas, CPE_DEC_HANDLE hCPE ); +#endif + /*--------------------------------------------------------------------------* * ivas_cpe_dec() @@ -77,6 +81,10 @@ ivas_error ivas_cpe_dec( Decoder_State **sts; int32_t ivas_total_brate; ivas_error error; +#ifdef MASA_AND_OBJECTS + int32_t cpe_brate; + int32_t element_brate_ref; +#endif error = IVAS_ERR_OK; @@ -93,10 +101,18 @@ ivas_error ivas_cpe_dec( sts[0]->BER_detect |= st_ivas->BER_detect; sts[1]->BER_detect |= st_ivas->BER_detect; +#ifdef MASA_AND_OBJECTS + element_brate_ref = hCPE->element_brate; +#endif + /*------------------------------------------------------------------* * Read stereo technology info & audio bandwidth *-----------------------------------------------------------------*/ +#ifdef MASA_AND_OBJECTS + stereo_mode_combined_format_dec( st_ivas, hCPE ); +#endif + read_stereo_mode_and_bwidth( hCPE, st_ivas ); /*----------------------------------------------------------------* @@ -162,7 +178,18 @@ ivas_error ivas_cpe_dec( { if ( st_ivas->hQMetaData != NULL && ivas_total_brate > IVAS_SID_5k2 ) { - stereo_dft_config( hCPE->hStereoDft == NULL ? NULL : hCPE->hStereoDft->hConfig, st_ivas->hQMetaData->bits_frame_nominal * FRAMES_PER_SEC, &sts[0]->bits_frame_nominal, &sts[1]->bits_frame_nominal ); +#ifdef MASA_AND_OBJECTS + if ( st_ivas->ivas_format == MASA_ISM_FORMAT ) + { + stereo_dft_config( hCPE->hStereoDft == NULL ? NULL : hCPE->hStereoDft->hConfig, (int32_t) ( 0.7f * st_ivas->hQMetaData->bits_frame_nominal * FRAMES_PER_SEC ), &sts[0]->bits_frame_nominal, &sts[1]->bits_frame_nominal ); + } + else + { +#endif + stereo_dft_config( hCPE->hStereoDft == NULL ? NULL : hCPE->hStereoDft->hConfig, st_ivas->hQMetaData->bits_frame_nominal * FRAMES_PER_SEC, &sts[0]->bits_frame_nominal, &sts[1]->bits_frame_nominal ); +#ifdef MASA_AND_OBJECTS + } +#endif } else { @@ -218,7 +245,18 @@ ivas_error ivas_cpe_dec( /* read DFT Stereo side info */ nb_bits = (int16_t) ( ( hCPE->element_brate ) / FRAMES_PER_SEC - 0.8f * sts[0]->bits_frame_nominal ); - sts[1]->bit_stream = sts[0]->bit_stream + ivas_total_brate / FRAMES_PER_SEC - 1 - nb_bits_metadata; +#ifdef MASA_AND_OBJECTS + cpe_brate = st_ivas->hCPE[0]->element_brate; + if ( st_ivas->ivas_format == MASA_ISM_FORMAT ) + { + sts[1]->bit_stream = sts[0]->bit_stream + cpe_brate / FRAMES_PER_SEC - 1 - nb_bits_metadata; + sts[1]->bit_stream += hCPE->brate_surplus / FRAMES_PER_SEC; + } + else +#endif + { + sts[1]->bit_stream = sts[0]->bit_stream + ivas_total_brate / FRAMES_PER_SEC - 1 - nb_bits_metadata; + } if ( ivas_total_brate == IVAS_SID_5k2 ) { @@ -226,7 +264,11 @@ ivas_error ivas_cpe_dec( sts[1]->bit_stream -= SID_FORMAT_NBITS; } +#ifdef MASA_AND_OBJECTS + if ( ( ( st_ivas->ivas_format == MASA_FORMAT && ivas_total_brate < MASA_STEREO_MIN_BITRATE ) || ( st_ivas->ivas_format == MASA_ISM_FORMAT && cpe_brate < MASA_STEREO_MIN_BITRATE ) ) && ivas_total_brate > IVAS_SID_5k2 ) +#else if ( st_ivas->ivas_format == MASA_FORMAT && ivas_total_brate < MASA_STEREO_MIN_BITRATE && ivas_total_brate > IVAS_SID_5k2 ) +#endif { sts[0]->total_brate = hCPE->element_brate; /* Only mono downmix was transmitted in this case */ } @@ -237,6 +279,14 @@ ivas_error ivas_cpe_dec( /* subtract metadata bitbudget */ sts[0]->total_brate -= ( nb_bits_metadata * FRAMES_PER_SEC ); + +#ifdef MASA_AND_OBJECTS + /* subtract bit-rate for combined format coding */ + if ( st_ivas->ivas_format == MASA_ISM_FORMAT && ( st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_DISC ) ) + { + sts[0]->total_brate += hCPE->brate_surplus; + } +#endif } else { @@ -248,6 +298,9 @@ ivas_error ivas_cpe_dec( /* signal bitrate for BW selection in the SCh */ sts[0]->bits_frame_channel = 0; sts[1]->bits_frame_channel = (int16_t) ( hCPE->element_brate / FRAMES_PER_SEC ); +#ifdef MASA_AND_OBJECTS + sts[1]->bits_frame_channel += (int16_t) ( hCPE->brate_surplus / FRAMES_PER_SEC ); +#endif if ( st_ivas->hQMetaData != NULL ) { sts[1]->bits_frame_channel -= st_ivas->hQMetaData->metadata_max_bits; @@ -255,6 +308,16 @@ ivas_error ivas_cpe_dec( } else if ( hCPE->element_mode == IVAS_CPE_MDCT ) { +#ifdef MASA_AND_OBJECTS + /* compute bit-rate surplus per channel in combined format coding */ + int32_t brate_surplus[CPE_CHANNELS]; + if ( st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_DISC ) + { + brate_surplus[0] = ( ( hCPE->brate_surplus / FRAMES_PER_SEC ) >> 1 ) * FRAMES_PER_SEC; + brate_surplus[1] = hCPE->brate_surplus - brate_surplus[0]; + } +#endif + if ( is_DTXrate( ivas_total_brate ) == 1 && ( sts[0]->first_CNG == 0 || sts[1]->first_CNG == 0 ) ) { if ( ( error = initMdctStereoDtxData( hCPE ) ) != IVAS_ERR_OK ) @@ -279,6 +342,15 @@ ivas_error ivas_cpe_dec( } sts[n]->bits_frame_nominal = (int16_t) ( sts[n]->total_brate / FRAMES_PER_SEC ); sts[n]->bits_frame_channel = (int16_t) ( ( hCPE->element_brate / FRAMES_PER_SEC ) / n_channels ); + +#ifdef MASA_AND_OBJECTS + /* subtract bit-rate for combined format coding */ + if ( st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_DISC ) + { + sts[n]->bits_frame_channel += (int16_t) ( brate_surplus[n] / FRAMES_PER_SEC ); + sts[n]->total_brate += brate_surplus[n]; + } +#endif } if ( !st_ivas->hMCT ) @@ -343,7 +415,12 @@ ivas_error ivas_cpe_dec( { if ( !st_ivas->bfi ) { - tdm_configure_dec( hCPE, &tdm_ratio_idx, nb_bits_metadata ); + tdm_configure_dec( +#ifdef MASA_AND_OBJECTS + st_ivas->ivas_format, + st_ivas->ism_mode, +#endif + hCPE, &tdm_ratio_idx, nb_bits_metadata ); sts[1]->bit_stream = sts[0]->bit_stream + ( sts[0]->total_brate / FRAMES_PER_SEC ); } @@ -489,6 +566,13 @@ ivas_error ivas_cpe_dec( hCPE->last_element_brate = hCPE->element_brate; hCPE->last_element_mode = hCPE->element_mode; +#ifdef MASA_AND_OBJECTS + if ( st_ivas->ivas_format == MASA_ISM_FORMAT ) + { + hCPE->element_brate = element_brate_ref; + } +#endif + if ( hCPE->element_mode == IVAS_CPE_DFT || hCPE->element_mode == IVAS_CPE_TD ) { stereo_cng_dec_update( hCPE, ivas_total_brate ); @@ -517,9 +601,15 @@ ivas_error ivas_cpe_dec( { dbgwrite( output[j], sizeof( float ), output_frame, 1, fname( debug_dir, "output.cpe", j, cpe_id, DEC ) ); } - tmpF = 0; - dbgwrite( &tmpF, sizeof( float ), 1, output_frame, fname( debug_dir, "output.sce", 0, cpe_id, DEC ) ); - dbgwrite( &tmpF, sizeof( float ), 1, output_frame, fname( debug_dir, "output.mct", 0, cpe_id, DEC ) ); + +#ifdef MASA_AND_OBJECTS + if ( st_ivas->ivas_format != MASA_ISM_FORMAT ) + { + tmpF = 0; + dbgwrite( &tmpF, sizeof( float ), 1, output_frame, fname( debug_dir, "output.sce", 0, cpe_id, DEC ) ); + dbgwrite( &tmpF, sizeof( float ), 1, output_frame, fname( debug_dir, "output.mct", 0, cpe_id, DEC ) ); + } +#endif } } #endif @@ -546,6 +636,9 @@ ivas_error create_cpe_dec( Decoder_State *st; int32_t output_Fs; ivas_error error; +#ifdef MASA_AND_OBJECTS + int32_t cpe_brate; +#endif error = IVAS_ERR_OK; @@ -584,7 +677,11 @@ ivas_error create_cpe_dec( hCPE->lt_es_em = 0.0f; /* Note: nchan_out is considered to be related to the structure. This is nchan_out for CPE and for MASA_format is always 2. */ +#ifdef MASA_AND_OBJECTS + if ( st_ivas->ivas_format == SBA_FORMAT || st_ivas->ivas_format == MASA_FORMAT || st_ivas->ivas_format == MASA_ISM_FORMAT || st_ivas->ivas_format == MC_FORMAT ) +#else if ( st_ivas->ivas_format == SBA_FORMAT || st_ivas->ivas_format == MASA_FORMAT || st_ivas->ivas_format == MC_FORMAT ) +#endif { hCPE->nchan_out = CPE_CHANNELS; } @@ -593,7 +690,22 @@ ivas_error create_cpe_dec( hCPE->nchan_out = min( CPE_CHANNELS, st_ivas->hDecoderConfig->nchan_out ); } +#ifdef MASA_AND_OBJECTS + if ( st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_DISC ) + { + cpe_brate = element_brate; + } + else + { + cpe_brate = st_ivas->hDecoderConfig->ivas_total_brate; + } + + if ( ( ( st_ivas->ivas_format == MASA_FORMAT && st_ivas->hDecoderConfig->ivas_total_brate < MASA_STEREO_MIN_BITRATE ) || + ( st_ivas->ivas_format == MASA_ISM_FORMAT && cpe_brate < MASA_STEREO_MIN_BITRATE ) ) && + st_ivas->hDecoderConfig->ivas_total_brate > IVAS_SID_5k2 ) +#else if ( st_ivas->ivas_format == MASA_FORMAT && st_ivas->hDecoderConfig->ivas_total_brate < MASA_STEREO_MIN_BITRATE && st_ivas->hDecoderConfig->ivas_total_brate > IVAS_SID_5k2 ) +#endif { hCPE->nchan_out = 1; } @@ -604,14 +716,23 @@ ivas_error create_cpe_dec( set_f( hCPE->prev_synth[n], 0, NS2SA( output_Fs, IVAS_DEC_DELAY_NS - STEREO_DFT32MS_OVL_NS ) ); } +#ifdef MASA_AND_OBJECTS + hCPE->brate_surplus = 0; +#endif + /*-----------------------------------------------------------------* * DFT stereo I/O Buffers: allocate and initialize *-----------------------------------------------------------------*/ for ( i = 0; i < CPE_CHANNELS; i++ ) { +#ifdef MASA_AND_OBJECTS + if ( st_ivas->ivas_format == STEREO_FORMAT || st_ivas->ivas_format == MASA_FORMAT || st_ivas->ivas_format == MASA_ISM_FORMAT || + ( st_ivas->ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCMASA ) || st_ivas->sba_dirac_stereo_flag ) +#else if ( st_ivas->ivas_format == STEREO_FORMAT || st_ivas->ivas_format == MASA_FORMAT || ( st_ivas->ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCMASA ) || st_ivas->sba_dirac_stereo_flag ) +#endif { if ( ( hCPE->input_mem[i] = (float *) malloc( sizeof( float ) * NS2SA( output_Fs, STEREO_DFT32MS_OVL_NS ) ) ) == NULL ) { @@ -1022,3 +1143,48 @@ static void read_stereo_mode_and_bwidth( return; } + + +#ifdef MASA_AND_OBJECTS +/*------------------------------------------------------------------------- + * stereo_mode_combined_format_dec() + * + * Set stereo format in a combined format + *-------------------------------------------------------------------------*/ + +static void stereo_mode_combined_format_dec( + const Decoder_Struct *st_ivas, /* i : decoder main structure */ + CPE_DEC_HANDLE hCPE /* i/o: CPE handle */ +) +{ + int32_t element_brate_ref; + + if ( st_ivas->ivas_format == MASA_ISM_FORMAT ) + { + element_brate_ref = hCPE->element_brate; + + if ( st_ivas->ism_mode == ISM_MASA_MODE_DISC && + ( ( st_ivas->nchan_ism == 3 && st_ivas->hDecoderConfig->ivas_total_brate == IVAS_96k ) || + ( st_ivas->nchan_ism == 4 && st_ivas->hDecoderConfig->ivas_total_brate == IVAS_128k ) ) ) + { + /* read OMASA stereo mode signalling */ + if ( get_next_indice( hCPE->hCoreCoder[0], NBITS_ELEMENT_MODE ) ) + { + hCPE->element_mode = IVAS_CPE_MDCT; + } + else + { + hCPE->element_mode = IVAS_CPE_DFT; + } + + if ( hCPE->element_mode == IVAS_CPE_MDCT ) + { + hCPE->element_brate = IVAS_64k; + hCPE->brate_surplus -= ( hCPE->element_brate - element_brate_ref ); + } + } + } + + return; +} +#endif diff --git a/lib_dec/ivas_dec.c b/lib_dec/ivas_dec.c index 5ca878a00ec58382864b493b2665782dbb4f20a9..facefc96cd9b465d0c8aa78f92ce57f35d629806 100644 --- a/lib_dec/ivas_dec.c +++ b/lib_dec/ivas_dec.c @@ -65,7 +65,11 @@ ivas_error ivas_dec( float output[MAX_OUTPUT_CHANNELS][L_FRAME48k]; /* 'float' buffer for output synthesis, MAX_OUTPUT_CHANNELS channels */ int16_t nchan_remapped; float output_lfe_ch[L_FRAME48k]; +#ifdef MASA_AND_OBJECTS + int16_t nb_bits_metadata[MAX_SCE + 1]; +#else int16_t nb_bits_metadata[MAX_SCE]; +#endif int32_t output_Fs, ivas_total_brate; AUDIO_CONFIG output_config; float pan_left, pan_right; @@ -74,6 +78,9 @@ ivas_error ivas_dec( #ifdef VLBR_20MS_MD int16_t num_md_sub_frames; #endif +#ifdef MASA_AND_OBJECTS + int32_t ism_total_brate; +#endif error = IVAS_ERR_OK; @@ -445,7 +452,7 @@ ivas_error ivas_dec( { #ifdef FIX_564 /* loudness correction */ - ivas_dirac_dec_binaural_sba_gain( output, nchan_remapped, output_frame ); + ivas_dirac_dec_binaural_gain( output, nchan_remapped, output_frame ); #else float gain; @@ -489,6 +496,122 @@ ivas_error ivas_dec( ivas_sba_upmixer_renderer( st_ivas, output, output_frame ); /* Note: ivas_sba_linear_renderer() or ivas_dirac_dec() are called internally */ } } +#ifdef MASA_AND_OBJECTS + // Todo OMASA JBM: Check here for p_output vs. output and possibly also metadata indices + else if ( st_ivas->ivas_format == MASA_ISM_FORMAT ) + { + int16_t nchan_ism, nchan_transport_ism; + int16_t dirac_bs_md_write_idx; + + st = st_ivas->hCPE[0]->hCoreCoder[0]; + set_s( nb_bits_metadata, 0, MAX_SCE + 1 ); + + /* Set the number of objects for the parametric rendering */ + dirac_bs_md_write_idx = 0; + if ( st_ivas->hDirAC != NULL ) + { + st_ivas->hDirAC->numIsmDirections = 0; + if ( st_ivas->ism_mode != ISM_MASA_MODE_DISC && st_ivas->ism_mode != ISM_MASA_MODE_MASA_ONE_OBJ ) + { + st_ivas->hDirAC->numIsmDirections = st_ivas->nchan_ism; + } + + dirac_bs_md_write_idx = st_ivas->hDirAC->dirac_bs_md_write_idx; /* Store the write-index for this frame */ + } + + /* MASA metadata decoding */ + if ( ( error = ivas_masa_decode( st_ivas, st, &nb_bits_metadata[0] ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* Configuration of combined-format bit-budget distribution */ + ivas_set_surplus_brate_dec( st_ivas, &ism_total_brate ); + + st->bit_stream = &( st_ivas->bit_stream[( ism_total_brate / FRAMES_PER_SEC )] ); + + /* set ISM parameters and decode ISM metadata in OMASA format */ + if ( ( error = ivas_omasa_ism_metadata_dec( st_ivas, ism_total_brate, &nchan_ism, &nchan_transport_ism, dirac_bs_md_write_idx, &nb_bits_metadata[1] ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* decode ISM channels */ + for ( n = 0; n < nchan_transport_ism; n++ ) + { + if ( ( error = ivas_sce_dec( st_ivas, n, &output[st_ivas->nchan_transport + n], output_frame, nb_bits_metadata[1] ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + /* decode MASA channels */ + if ( ( error = ivas_cpe_dec( st_ivas, 0, output, output_frame, nb_bits_metadata[0] ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( st_ivas->hCPE[0]->nchan_out == 1 ) + { + mvr2r( output[0], output[1], output_frame ); /* Copy mono signal to stereo output channels */ + } + + /* HP filtering */ + for ( n = 0; n < getNumChanSynthesis( st_ivas ); n++ ) + { + hp20( output[n], output_frame, st_ivas->mem_hp20_out[n], output_Fs ); + } + + /* Set edited object positions, if editing enabled */ + ivas_masa_ism_set_edited_objects( st_ivas ); + + /* Rendering */ + if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) + { + if ( st_ivas->ism_mode == ISM_MASA_MODE_DISC && st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC ) + { + if ( ( error = ivas_omasa_dirac_td_binaural( st_ivas, output, output_frame ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else + { + ivas_dirac_dec_binaural( st_ivas, st_ivas->hCombinedOrientationData, output, st_ivas->nchan_transport ); + } + } + else if ( st_ivas->renderer_type == RENDERER_MONO_DOWNMIX ) + { + ivas_mono_downmix_render_passive( st_ivas, output, output_frame ); + } + else if ( st_ivas->renderer_type == RENDERER_DIRAC ) + { + ivas_omasa_dirac_rend( st_ivas, output, output_frame ); + } + +#ifdef OMASA_EXT_OUTPUT + if ( st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_EXTERNAL ) + { + /* sanity check in case of bitrate switching */ + if ( st_ivas->ism_mode != ISM_MASA_MODE_DISC ) + { + return IVAS_ERROR( IVAS_ERR_INVALID_OUTPUT_FORMAT, "Incorrect output configuration specified for combined MASA and ISM format" ); + } + + /* in case of external rendering, rearrange the channels order */ + mvr2r( output[0], output[MAX_OUTPUT_CHANNELS - 2], output_frame ); + mvr2r( output[1], output[MAX_OUTPUT_CHANNELS - 1], output_frame ); + + for ( n = 0; n < nchan_transport_ism; n++ ) + { + mvr2r( output[st_ivas->nchan_transport + n], output[n], output_frame ); + } + mvr2r( output[MAX_OUTPUT_CHANNELS - 2], output[n], output_frame ); + mvr2r( output[MAX_OUTPUT_CHANNELS - 1], output[++n], output_frame ); + } +#endif + } +#endif else if ( st_ivas->ivas_format == MC_FORMAT ) { st = ( st_ivas->nSCE > 0 ) ? st_ivas->hSCE[0]->hCoreCoder[0] : st_ivas->hCPE[0]->hCoreCoder[0]; @@ -897,6 +1020,10 @@ ivas_error ivas_dec( st_ivas->ini_active_frame++; } +#ifdef MASA_AND_OBJECTS + st_ivas->last_ivas_format = st_ivas->ivas_format; +#endif + #ifdef DEBUG_MODE_INFO dbgwrite( &st_ivas->bfi, sizeof( int16_t ), 1, output_frame, "res/bfi" ); dbgwrite( &st_ivas->BER_detect, sizeof( int16_t ), 1, output_frame, "res/BER_detect" ); diff --git a/lib_dec/ivas_dirac_dec.c b/lib_dec/ivas_dirac_dec.c index 766f4ff08fe05ea389e53845c393a6b5fda5f734..ef2ec470a229755eec2adec1f4456906b027f411 100644 --- a/lib_dec/ivas_dirac_dec.c +++ b/lib_dec/ivas_dirac_dec.c @@ -51,69 +51,206 @@ * Local function prototypes *-----------------------------------------------------------------------*/ -static ivas_error ivas_dirac_dec_config_internal( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ - const DIRAC_CONFIG_FLAG flag_config_inp /* i/ : Flag determining if we open or reconfigure the DirAC decoder */ +static ivas_error ivas_dirac_alloc_mem( DIRAC_DEC_HANDLE hDirAC, const RENDERER_TYPE renderer_type, DIRAC_DEC_STACK_MEM_HANDLE hDirAC_mem, const int16_t hodirac_flag ); + +static void ivas_dirac_free_mem( DIRAC_DEC_STACK_MEM_HANDLE hDirAC_mem ); + +static void initDiffuseResponses( float *diffuse_response_function, const int16_t num_channels, AUDIO_CONFIG output_config, IVAS_OUTPUT_SETUP hOutSetup, const int16_t ambisonics_order, const IVAS_FORMAT ivas_format, int16_t *num_ele_spk_no_diffuse_rendering, AUDIO_CONFIG transport_config ); + +static void computeIntensityVector_dec( float Cldfb_RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], float Cldfb_ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], const int16_t num_frequency_bands, float *intensity_real_x, float *intensity_real_y, float *intensity_real_z ); + +static void protoSignalComputation_shd( float RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], float ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], float *proto_direct_buffer_f, float *proto_diffuse_buffer_f, float *reference_power, const int16_t slot_index, const int16_t num_inputs, const int16_t num_outputs_diff, const int16_t num_freq_bands, float *p_Rmat ); + +static void protoSignalComputation1( float RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], float ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], float *proto_frame_f, float *proto_direct_buffer_f, float *reference_power, float *proto_power_smooth, const int16_t slot_index, const int16_t num_outputs_diff, const int16_t num_freq_bands ); + +static void protoSignalComputation2( float RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], float ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], float *proto_frame_f, float *proto_direct_buffer_f, float *reference_power, float *proto_power_smooth, const int16_t isloudspeaker, const int16_t slot_index, const int16_t num_freq_bands, MASA_STEREO_TYPE_DETECT *stereo_type_detect ); + +static void protoSignalComputation4( float RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], float ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], float *proto_frame_f, float *proto_direct_buffer_f, float *reference_power, float *proto_power_smooth, const int16_t slot_index, const int16_t num_outputs_diff, const int16_t num_freq_bands, const float *mtx_hoa_decoder, const int16_t nchan_transport, const int16_t *sba_map_tc_ind ); + +static void ivas_dirac_dec_compute_diffuse_proto( DIRAC_DEC_HANDLE hDirAC, const int16_t slot_idx ); + +static void computeDirectionAngles( float *intensity_real_x, float *intensity_real_y, float *intensity_real_z, const int16_t num_frequency_bands, int16_t *azimuth, int16_t *elevation ); + +static void ivas_masa_init_stereotype_detection( MASA_STEREO_TYPE_DETECT *stereo_type_detect ); + +static void ivas_masa_stereotype_detection( MASA_STEREO_TYPE_DETECT *stereo_type_detect ); + +static void ivas_lfe_synth_with_cldfb( MCMASA_LFE_SYNTH_DATA_HANDLE hMasaLfeSynth, float RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], float ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], float RealBufferLfe[MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], float ImagBufferLfe[MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], const int16_t slot_index, const int16_t subframe_index, const int16_t nchan_transport ); + +static void rotateAziEle_DirAC( int16_t *azi, int16_t *ele, const int16_t band1, const int16_t band2, const float *p_Rmat ); + + +/*------------------------------------------------------------------------- + * ivas_dirac_dec_open() + * + * Open decoder DirAC handle + *-------------------------------------------------------------------------*/ + +ivas_error ivas_dirac_dec_open( + Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ ) { - DIRAC_DEC_HANDLE hDirAC; ivas_error error; - DIRAC_CONFIG_FLAG flag_config; - flag_config = ( flag_config_inp == DIRAC_RECONFIGURE_MODE ) ? DIRAC_RECONFIGURE : flag_config_inp; error = IVAS_ERR_OK; - hDirAC = NULL; - - if ( flag_config == DIRAC_RECONFIGURE ) + if ( ( error = ivas_dirac_dec_config( st_ivas, DIRAC_OPEN ) ) != IVAS_ERR_OK ) { - hDirAC = st_ivas->hDirAC; + return error; } - else if ( flag_config == DIRAC_OPEN ) + + return error; +} + + +/*------------------------------------------------------------------------- + * ivas_dirac_allocate_parameters() + * + * Allocate and initialize DirAC parameters + *-------------------------------------------------------------------------*/ + +ivas_error ivas_dirac_allocate_parameters( + DIRAC_DEC_HANDLE hDirAC, /* i/o: decoder DirAC handle */ + const int16_t params_flag /* i : set of parameters flag */ +) +{ + int16_t i; + + if ( params_flag == 1 ) { - /*-----------------------------------------------------------------* - * prepare library opening - *-----------------------------------------------------------------*/ + if ( ( hDirAC->azimuth = (int16_t **) malloc( hDirAC->dirac_md_buffer_length * sizeof( int16_t * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } - if ( ( hDirAC = (DIRAC_DEC_HANDLE) malloc( sizeof( DIRAC_DEC_DATA ) ) ) == NULL ) + if ( ( hDirAC->elevation = (int16_t **) malloc( hDirAC->dirac_md_buffer_length * sizeof( int16_t * ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); } - if ( ( hDirAC->hConfig = (DIRAC_CONFIG_DATA_HANDLE) malloc( sizeof( DIRAC_CONFIG_DATA ) ) ) == NULL ) + if ( ( hDirAC->diffuseness_vector = (float **) malloc( hDirAC->dirac_md_buffer_length * sizeof( float * ) ) ) == NULL ) { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC Config\n" ) ); + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); } - hDirAC->hParamIsm = NULL; - hDirAC->hParamIsmRendering = NULL; - st_ivas->hDirAC = hDirAC; - } + if ( ( hDirAC->energy_ratio1 = (float **) malloc( hDirAC->dirac_md_buffer_length * sizeof( float * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } + if ( ( hDirAC->spreadCoherence = (float **) malloc( hDirAC->dirac_md_buffer_length * sizeof( float * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } - /*-----------------------------------------------------------------* - * DirAC main configuration - *-----------------------------------------------------------------*/ + if ( ( hDirAC->surroundingCoherence = (float **) malloc( hDirAC->dirac_md_buffer_length * sizeof( float * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } - if ( ( error = ivas_dirac_config( (void *) st_ivas, DEC ) ) != IVAS_ERR_OK ) - { - return error; - } + for ( i = 0; i < hDirAC->dirac_md_buffer_length; i++ ) + { + if ( ( hDirAC->azimuth[i] = (int16_t *) malloc( hDirAC->num_freq_bands * sizeof( int16_t ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } + set_s( hDirAC->azimuth[i], 0, hDirAC->num_freq_bands ); - if ( flag_config == DIRAC_OPEN ) + if ( ( hDirAC->elevation[i] = (int16_t *) malloc( hDirAC->num_freq_bands * sizeof( int16_t ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } + set_s( hDirAC->elevation[i], 0, hDirAC->num_freq_bands ); + + if ( ( hDirAC->diffuseness_vector[i] = (float *) malloc( hDirAC->num_freq_bands * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } + set_f( hDirAC->diffuseness_vector[i], 1.0f, hDirAC->num_freq_bands ); + + if ( ( hDirAC->energy_ratio1[i] = (float *) malloc( hDirAC->num_freq_bands * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } + set_f( hDirAC->energy_ratio1[i], 0.0f, hDirAC->num_freq_bands ); + + if ( ( hDirAC->spreadCoherence[i] = (float *) malloc( hDirAC->num_freq_bands * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } + set_f( hDirAC->spreadCoherence[i], 0.0f, hDirAC->num_freq_bands ); + + if ( ( hDirAC->surroundingCoherence[i] = (float *) malloc( hDirAC->num_freq_bands * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } + set_f( hDirAC->surroundingCoherence[i], 0.0f, hDirAC->num_freq_bands ); + } + } + else if ( params_flag == 2 ) { - hDirAC->spar_to_dirac_write_idx = st_ivas->ivas_format == SBA_FORMAT ? DELAY_DIRAC_PARAM_DEC_SFR : 0; - hDirAC->dithering_seed = DIRAC_DITH_SEED; - st_ivas->hDirAC = hDirAC; + if ( ( hDirAC->azimuth2 = (int16_t **) malloc( hDirAC->dirac_md_buffer_length * sizeof( int16_t * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } + + if ( ( hDirAC->elevation2 = (int16_t **) malloc( hDirAC->dirac_md_buffer_length * sizeof( int16_t * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } + + if ( ( hDirAC->energy_ratio2 = (float **) malloc( hDirAC->dirac_md_buffer_length * sizeof( float * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } + + if ( ( hDirAC->spreadCoherence2 = (float **) malloc( hDirAC->dirac_md_buffer_length * sizeof( float * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } + + for ( i = 0; i < hDirAC->dirac_md_buffer_length; i++ ) + { + if ( ( hDirAC->azimuth2[i] = (int16_t *) malloc( hDirAC->num_freq_bands * sizeof( int16_t ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } + set_s( hDirAC->azimuth2[i], 0, hDirAC->num_freq_bands ); + + if ( ( hDirAC->elevation2[i] = (int16_t *) malloc( hDirAC->num_freq_bands * sizeof( int16_t ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } + set_s( hDirAC->elevation2[i], 0, hDirAC->num_freq_bands ); + + if ( ( hDirAC->energy_ratio2[i] = (float *) malloc( hDirAC->num_freq_bands * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } + set_f( hDirAC->energy_ratio2[i], 0.0f, hDirAC->num_freq_bands ); + + if ( ( hDirAC->spreadCoherence2[i] = (float *) malloc( hDirAC->num_freq_bands * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } + set_f( hDirAC->spreadCoherence2[i], 0.0f, hDirAC->num_freq_bands ); + } } - return error; + return IVAS_ERR_OK; } -static ivas_error ivas_dirac_rend_config( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ - const DIRAC_CONFIG_FLAG flag_config_inp, /* i/ : Flag determining if we open or reconfigure the DirAC decoder */ - const int16_t dec_param_estim_old ) + +/*------------------------------------------------------------------------- + * ivas_dirac_dec_config() + * + * Open or reconfigure decoder DirAC/MASA handle + *-------------------------------------------------------------------------*/ + +ivas_error ivas_dirac_dec_config( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const DIRAC_CONFIG_FLAG flag_config_inp /* i/ : Flag determining if we open or reconfigure the DirAC decoder */ +) { DIRAC_DEC_HANDLE hDirAC; int16_t nchan_out_woLFE; @@ -125,30 +262,27 @@ static ivas_error ivas_dirac_rend_config( float *proto_frame_f_old; int16_t proto_signal_decorr_on_old; uint16_t i, j, k; + int16_t dec_param_estim_old; float ls_azimuth[MAX_OUTPUT_CHANNELS]; float ls_elevation[MAX_OUTPUT_CHANNELS]; int32_t output_Fs, ivas_total_brate; ivas_error error; int16_t nchan_transport_orig; int16_t hodirac_flag; + int16_t map_idx; DIRAC_CONFIG_FLAG flag_config; - DIRAC_REND_HANDLE hDirACRend; - SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom; flag_config = ( flag_config_inp == DIRAC_RECONFIGURE_MODE ) ? DIRAC_RECONFIGURE : flag_config_inp; error = IVAS_ERR_OK; - hDirACRend = NULL; + hDirAC = NULL; output_Fs = st_ivas->hDecoderConfig->output_Fs; ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; hodirac_flag = ivas_get_hodirac_flag( ivas_total_brate, st_ivas->sba_analysis_order ); - hDirAC = st_ivas->hDirAC; - hSpatParamRendCom = st_ivas->hSpatParamRendCom; - if ( flag_config == DIRAC_RECONFIGURE ) { - hDirACRend = st_ivas->hDirACRend; + hDirAC = st_ivas->hDirAC; } else if ( flag_config == DIRAC_OPEN ) { @@ -156,21 +290,29 @@ static ivas_error ivas_dirac_rend_config( * prepare library opening *-----------------------------------------------------------------*/ - if ( ( hDirACRend = (DIRAC_REND_HANDLE) malloc( sizeof( DIRAC_REND_DATA ) ) ) == NULL ) + if ( ( hDirAC = (DIRAC_DEC_HANDLE) malloc( sizeof( DIRAC_DEC_DATA ) ) ) == NULL ) { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC renderer\n" ) ); + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); } + if ( ( hDirAC->hConfig = (DIRAC_CONFIG_DATA_HANDLE) malloc( sizeof( DIRAC_CONFIG_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC Config\n" ) ); + } nchan_transport_old = 0; + hDirAC->hParamIsm = NULL; + hDirAC->hParamIsmRendering = NULL; + st_ivas->hDirAC = hDirAC; } + dec_param_estim_old = ( flag_config == DIRAC_RECONFIGURE ) ? hDirAC->hConfig->dec_param_estim : FALSE; nchan_transport_old = 0; num_outputs_dir_old = 0; num_outputs_diff_old = 0; num_protos_diff_old = 0; nchan_transport_orig = st_ivas->nchan_transport; - if ( st_ivas->ivas_format == SBA_FORMAT ) + if ( st_ivas->ivas_format == SBA_FORMAT && !( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) { st_ivas->nchan_transport = ivas_sba_get_nchan_metadata( st_ivas->sba_analysis_order, st_ivas->hDecoderConfig->ivas_total_brate ); } @@ -187,40 +329,58 @@ static ivas_error ivas_dirac_rend_config( ivas_sba_config( ivas_total_brate, st_ivas->sba_analysis_order, -1, &nchan_transport_old, st_ivas->sba_planar, &tmp1, &tmp2, &tmp3 ); } + /*-----------------------------------------------------------------* + * DirAC main configuration + *-----------------------------------------------------------------*/ + + if ( ( error = ivas_dirac_config( (void *) st_ivas, DEC ) ) != IVAS_ERR_OK ) + { + return error; + } + /*-----------------------------------------------------------------* * output setup: for parametric binaural renderer, use output setup, otherwise internal setup *-----------------------------------------------------------------*/ - hDirACRend->hOutSetup = st_ivas->hIntSetup; - nchan_out_woLFE = hDirACRend->hOutSetup.nchan_out_woLFE; + if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) + { + hDirAC->hOutSetup = st_ivas->hOutSetup; + + hDirAC->hConfig->dec_param_estim = FALSE; + } + else + { + hDirAC->hOutSetup = st_ivas->hIntSetup; + } + nchan_out_woLFE = hDirAC->hOutSetup.nchan_out_woLFE; - if ( hDirACRend->hOutSetup.ls_azimuth != NULL && hDirACRend->hOutSetup.ls_elevation != NULL ) + if ( hDirAC->hOutSetup.ls_azimuth != NULL && hDirAC->hOutSetup.ls_elevation != NULL ) { - mvr2r( hDirACRend->hOutSetup.ls_azimuth, ls_azimuth, nchan_out_woLFE ); - mvr2r( hDirACRend->hOutSetup.ls_elevation, ls_elevation, nchan_out_woLFE ); + mvr2r( hDirAC->hOutSetup.ls_azimuth, ls_azimuth, nchan_out_woLFE ); + mvr2r( hDirAC->hOutSetup.ls_elevation, ls_elevation, nchan_out_woLFE ); } - if ( hDirACRend->hOutSetup.ambisonics_order == -1 ) + if ( hDirAC->hOutSetup.ambisonics_order == -1 ) { - hDirACRend->hOutSetup.ambisonics_order = SBA_HOA3_ORDER; /* Order 3 is used by default in DirAC for SHD processing */ - if ( hDirACRend->hOutSetup.output_config == AUDIO_CONFIG_MONO || hDirACRend->hOutSetup.output_config == AUDIO_CONFIG_STEREO ) + hDirAC->hOutSetup.ambisonics_order = SBA_HOA3_ORDER; /* Order 3 is used by default in DirAC for SHD processing */ + if ( hDirAC->hOutSetup.output_config == AUDIO_CONFIG_MONO || hDirAC->hOutSetup.output_config == AUDIO_CONFIG_STEREO ) { - hDirACRend->hOutSetup.ambisonics_order = SBA_FOA_ORDER; + hDirAC->hOutSetup.ambisonics_order = SBA_FOA_ORDER; } } - else if ( hDirACRend->hOutSetup.ambisonics_order >= SBA_FOA_ORDER ) + else if ( hDirAC->hOutSetup.ambisonics_order >= SBA_FOA_ORDER ) { mvr2r( ls_azimuth_4d4, ls_azimuth, DIRAC_HOA_RENDERING_NUM_VIRT_DECORR_LS ); mvr2r( ls_elevation_4d4, ls_elevation, DIRAC_HOA_RENDERING_NUM_VIRT_DECORR_LS ); } - if ( hDirACRend->hOutSetup.separateChannelEnabled && ( hDirACRend->hOutSetup.output_config == AUDIO_CONFIG_5_1 || hDirACRend->hOutSetup.output_config == AUDIO_CONFIG_7_1 || hDirACRend->hOutSetup.output_config == AUDIO_CONFIG_5_1_2 || hDirACRend->hOutSetup.output_config == AUDIO_CONFIG_5_1_4 || hDirACRend->hOutSetup.output_config == AUDIO_CONFIG_7_1_4 || ( hDirACRend->hOutSetup.output_config == AUDIO_CONFIG_LS_CUSTOM && st_ivas->hLsSetupCustom->separate_ch_found ) ) ) + if ( hDirAC->hOutSetup.separateChannelEnabled && ( hDirAC->hOutSetup.output_config == AUDIO_CONFIG_5_1 || hDirAC->hOutSetup.output_config == AUDIO_CONFIG_7_1 || hDirAC->hOutSetup.output_config == AUDIO_CONFIG_5_1_2 || hDirAC->hOutSetup.output_config == AUDIO_CONFIG_5_1_4 || hDirAC->hOutSetup.output_config == AUDIO_CONFIG_7_1_4 || ( hDirAC->hOutSetup.output_config == AUDIO_CONFIG_LS_CUSTOM && st_ivas->hLsSetupCustom->separate_ch_found ) ) ) { /* Remove the channel of the separated signal from the output setup of the spatial synthesis */ - hDirACRend->hOutSetup.nchan_out_woLFE--; - nchan_out_woLFE = hDirACRend->hOutSetup.nchan_out_woLFE; - mvr2r( &ls_azimuth[hDirACRend->hOutSetup.separateChannelIndex + 1], &ls_azimuth[hDirACRend->hOutSetup.separateChannelIndex], nchan_out_woLFE - hDirACRend->hOutSetup.separateChannelIndex ); - mvr2r( &ls_elevation[hDirACRend->hOutSetup.separateChannelIndex + 1], &ls_elevation[hDirACRend->hOutSetup.separateChannelIndex], nchan_out_woLFE - hDirACRend->hOutSetup.separateChannelIndex ); + hDirAC->hOutSetup.nchan_out_woLFE--; + nchan_out_woLFE = hDirAC->hOutSetup.nchan_out_woLFE; + mvr2r( &ls_azimuth[hDirAC->hOutSetup.separateChannelIndex + 1], &ls_azimuth[hDirAC->hOutSetup.separateChannelIndex], nchan_out_woLFE - hDirAC->hOutSetup.separateChannelIndex ); + mvr2r( &ls_elevation[hDirAC->hOutSetup.separateChannelIndex + 1], &ls_elevation[hDirAC->hOutSetup.separateChannelIndex], nchan_out_woLFE - hDirAC->hOutSetup.separateChannelIndex ); } /*-----------------------------------------------------------------* @@ -229,64 +389,114 @@ static ivas_error ivas_dirac_rend_config( st_ivas->nchan_transport = nchan_transport_orig; - if ( nchan_transport_orig > 2 && hDirACRend->hOutSetup.is_loudspeaker_setup && st_ivas->renderer_type == RENDERER_DIRAC && !hodirac_flag ) + if ( flag_config == DIRAC_OPEN ) + { + hDirAC->slot_size = (int16_t) ( ( output_Fs / FRAMES_PER_SEC ) / CLDFB_NO_COL_MAX ); + set_s( hDirAC->subframe_nbslots, 0, MAX_JBM_SUBFRAMES_5MS ); + set_s( hDirAC->subframe_nbslots, JBM_CLDFB_SLOTS_IN_SUBFRAME, DEFAULT_JBM_SUBFRAMES_5MS ); + hDirAC->nb_subframes = DEFAULT_JBM_SUBFRAMES_5MS; + hDirAC->subframes_rendered = 0; + hDirAC->slots_rendered = 0; + hDirAC->num_slots = DEFAULT_JBM_SUBFRAMES_5MS * JBM_CLDFB_SLOTS_IN_SUBFRAME; + } + + if ( st_ivas->ivas_format == SBA_FORMAT && flag_config == DIRAC_RECONFIGURE && ( ( ivas_total_brate > IVAS_256k && st_ivas->hDecoderConfig->last_ivas_total_brate <= IVAS_256k ) || ( ivas_total_brate <= IVAS_256k && st_ivas->hDecoderConfig->last_ivas_total_brate > IVAS_256k ) ) ) + { + if ( st_ivas->hDecoderConfig->ivas_total_brate > IVAS_256k && hDirAC->azimuth2 == NULL ) + { + if ( ( error = ivas_dirac_allocate_parameters( hDirAC, 2 ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else if ( st_ivas->hDecoderConfig->ivas_total_brate <= IVAS_256k && hDirAC->azimuth2 != NULL ) + { + ivas_dirac_deallocate_parameters( hDirAC, 2 ); + } + } + + /* band config needed only for SPAR with FOA output */ + if ( st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_FOA && st_ivas->ivas_format == SBA_FORMAT && !hodirac_flag ) + { + return IVAS_ERR_OK; + } + + if ( nchan_transport_orig > 2 && hDirAC->hOutSetup.is_loudspeaker_setup && st_ivas->renderer_type == RENDERER_DIRAC && !hodirac_flag ) + { + hDirAC->synthesisConf = DIRAC_SYNTHESIS_PSD_LS; + hDirAC->panningConf = DIRAC_PANNING_VBAP; + } + else if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) { - hDirACRend->synthesisConf = DIRAC_SYNTHESIS_PSD_LS; - hDirACRend->panningConf = DIRAC_PANNING_VBAP; + hDirAC->synthesisConf = DIRAC_SYNTHESIS_PSD_LS; + hDirAC->panningConf = DIRAC_PANNING_VBAP; } - else if ( ( st_ivas->ivas_format == MASA_FORMAT || st_ivas->mc_mode == MC_MODE_MCMASA ) && hDirACRend->hOutSetup.output_config == AUDIO_CONFIG_MONO ) + else if ( ( st_ivas->ivas_format == MASA_FORMAT || st_ivas->mc_mode == MC_MODE_MCMASA ) && hDirAC->hOutSetup.output_config == AUDIO_CONFIG_MONO ) { - hDirACRend->synthesisConf = DIRAC_SYNTHESIS_MONO; - hDirACRend->panningConf = DIRAC_PANNING_HOA3; + hDirAC->synthesisConf = DIRAC_SYNTHESIS_MONO; + hDirAC->panningConf = DIRAC_PANNING_HOA3; nchan_out_woLFE = 1; } - else if ( ( st_ivas->ivas_format == MASA_FORMAT || st_ivas->mc_mode == MC_MODE_MCMASA ) && hDirACRend->hOutSetup.is_loudspeaker_setup ) +#ifdef MASA_AND_OBJECTS + else if ( ( st_ivas->ivas_format == MASA_FORMAT || st_ivas->ivas_format == MASA_ISM_FORMAT || st_ivas->mc_mode == MC_MODE_MCMASA ) && hDirAC->hOutSetup.is_loudspeaker_setup ) +#else + else if ( ( st_ivas->ivas_format == MASA_FORMAT || st_ivas->mc_mode == MC_MODE_MCMASA ) && hDirAC->hOutSetup.is_loudspeaker_setup ) +#endif { - hDirACRend->synthesisConf = DIRAC_SYNTHESIS_PSD_LS; - hDirACRend->panningConf = DIRAC_PANNING_VBAP; + hDirAC->synthesisConf = DIRAC_SYNTHESIS_PSD_LS; + hDirAC->panningConf = DIRAC_PANNING_VBAP; } - else if ( st_ivas->ivas_format == MASA_FORMAT && !hDirACRend->hOutSetup.is_loudspeaker_setup && st_ivas->nchan_transport > 1 ) +#ifdef MASA_AND_OBJECTS + else if ( ( st_ivas->ivas_format == MASA_FORMAT || st_ivas->ivas_format == MASA_ISM_FORMAT ) && !hDirAC->hOutSetup.is_loudspeaker_setup && st_ivas->nchan_transport > 1 ) +#else + else if ( st_ivas->ivas_format == MASA_FORMAT && !hDirAC->hOutSetup.is_loudspeaker_setup && st_ivas->nchan_transport > 1 ) +#endif { - hDirACRend->synthesisConf = DIRAC_SYNTHESIS_PSD_SHD; - hDirACRend->panningConf = DIRAC_PANNING_HOA3; + hDirAC->synthesisConf = DIRAC_SYNTHESIS_PSD_SHD; + hDirAC->panningConf = DIRAC_PANNING_HOA3; } else { - hDirACRend->synthesisConf = DIRAC_SYNTHESIS_GAIN_SHD; - hDirACRend->panningConf = DIRAC_PANNING_HOA3; + hDirAC->synthesisConf = DIRAC_SYNTHESIS_GAIN_SHD; + hDirAC->panningConf = DIRAC_PANNING_HOA3; } if ( flag_config == DIRAC_OPEN ) { - if ( ( hDirACRend->frequency_axis = (float *) malloc( hSpatParamRendCom->num_freq_bands * sizeof( float ) ) ) == NULL ) + hDirAC->num_freq_bands = (int16_t) ( output_Fs * INV_CLDFB_BANDWIDTH + 0.5f ); + if ( ( hDirAC->frequency_axis = (float *) malloc( hDirAC->num_freq_bands * sizeof( float ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); } - set_f( hDirACRend->frequency_axis, 0.0f, hSpatParamRendCom->num_freq_bands ); + set_f( hDirAC->frequency_axis, 0.0f, hDirAC->num_freq_bands ); - ivas_dirac_dec_get_frequency_axis( hDirACRend->frequency_axis, output_Fs, hSpatParamRendCom->num_freq_bands ); + ivas_dirac_dec_get_frequency_axis( hDirAC->frequency_axis, output_Fs, hDirAC->num_freq_bands ); } - if ( ( st_ivas->ivas_format == MASA_FORMAT || st_ivas->mc_mode == MC_MODE_MCMASA ) && hDirACRend->panningConf == DIRAC_PANNING_HOA3 && nchan_transport == 2 ) + if ( ( st_ivas->ivas_format == MASA_FORMAT || st_ivas->mc_mode == MC_MODE_MCMASA ) && hDirAC->panningConf == DIRAC_PANNING_HOA3 && nchan_transport == 2 ) { - if ( ( flag_config == DIRAC_RECONFIGURE && hDirACRend->masa_stereo_type_detect == NULL ) || flag_config == DIRAC_OPEN ) + if ( ( flag_config == DIRAC_RECONFIGURE && hDirAC->masa_stereo_type_detect == NULL ) || flag_config == DIRAC_OPEN ) { - if ( ( hDirACRend->masa_stereo_type_detect = (MASA_STEREO_TYPE_DETECT *) malloc( sizeof( MASA_STEREO_TYPE_DETECT ) ) ) == NULL ) + if ( ( hDirAC->masa_stereo_type_detect = (MASA_STEREO_TYPE_DETECT *) malloc( sizeof( MASA_STEREO_TYPE_DETECT ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); } } - ivas_masa_init_stereotype_detection( hDirACRend->masa_stereo_type_detect ); + ivas_masa_init_stereotype_detection( hDirAC->masa_stereo_type_detect ); } else { - if ( flag_config == DIRAC_RECONFIGURE && hDirACRend->masa_stereo_type_detect != NULL ) + if ( flag_config == DIRAC_RECONFIGURE && hDirAC->masa_stereo_type_detect != NULL ) { - free( hDirACRend->masa_stereo_type_detect ); + free( hDirAC->masa_stereo_type_detect ); } - hDirACRend->masa_stereo_type_detect = NULL; + hDirAC->masa_stereo_type_detect = NULL; } +#ifdef MASA_AND_OBJECTS + hDirAC->numIsmDirections = 0; /* By default, no ism directions, set correct number runtime when needed */ +#endif + /*-----------------------------------------------------------------* * (re)configure sub-modules *-----------------------------------------------------------------*/ @@ -294,39 +504,45 @@ static ivas_error ivas_dirac_rend_config( /* prototype signal computation */ if ( flag_config == DIRAC_RECONFIGURE ) { - num_outputs_dir_old = hDirACRend->num_outputs_dir; - num_outputs_diff_old = hDirACRend->num_outputs_diff; - num_protos_diff_old = hDirACRend->num_protos_diff; + num_outputs_dir_old = hDirAC->num_outputs_dir; + num_outputs_diff_old = hDirAC->num_outputs_diff; + num_protos_diff_old = hDirAC->num_protos_diff; } /* allocate output setup related arrays */ - if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_PSD_LS ) + if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) + { + /* Two channels in parametric binaural rendering */ + hDirAC->num_outputs_diff = 2; + hDirAC->num_outputs_dir = 2; + } + else if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_PSD_LS ) { /* Directional and diffuses components in output LS format */ - hDirACRend->num_outputs_diff = nchan_out_woLFE; - hDirACRend->num_outputs_dir = nchan_out_woLFE; + hDirAC->num_outputs_diff = nchan_out_woLFE; + hDirAC->num_outputs_dir = nchan_out_woLFE; } - else if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) + else if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) { /* Directional and diffuses components in SHD */ /* Diffuseness components up to 1st order */ - hDirACRend->num_outputs_diff = ( min( hDirACRend->hOutSetup.ambisonics_order, 1 ) + 1 ) * ( min( hDirACRend->hOutSetup.ambisonics_order, 1 ) + 1 ); - if ( ( st_ivas->ivas_format == SBA_FORMAT ) && ( ivas_total_brate >= IVAS_96k ) && ( hDirACRend->hOutSetup.ambisonics_order > 1 ) && ( nchan_transport < 4 ) ) + hDirAC->num_outputs_diff = ( min( hDirAC->hOutSetup.ambisonics_order, 1 ) + 1 ) * ( min( hDirAC->hOutSetup.ambisonics_order, 1 ) + 1 ); + if ( ( st_ivas->ivas_format == SBA_FORMAT ) && ( ivas_total_brate >= IVAS_96k ) && ( hDirAC->hOutSetup.ambisonics_order > 1 ) && ( nchan_transport < 4 ) ) { - hDirACRend->num_outputs_diff += 2; /* Add 2nd-order planar components for HRs */ + hDirAC->num_outputs_diff += 2; /* Add 2nd-order planar components for HRs */ } - hDirACRend->num_outputs_dir = ivas_sba_get_nchan( hDirACRend->hOutSetup.ambisonics_order, 0 ); + hDirAC->num_outputs_dir = ivas_sba_get_nchan( hDirAC->hOutSetup.ambisonics_order, 0 ); } - else if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_PSD_SHD ) + else if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_PSD_SHD ) { - hDirACRend->num_outputs_diff = DIRAC_HOA_RENDERING_NUM_VIRT_DECORR_LS; - hDirACRend->num_outputs_dir = nchan_out_woLFE; + hDirAC->num_outputs_diff = DIRAC_HOA_RENDERING_NUM_VIRT_DECORR_LS; + hDirAC->num_outputs_dir = nchan_out_woLFE; } - else if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_MONO ) + else if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_MONO ) { - hDirACRend->num_outputs_diff = 1; /* There is one output channel in mono */ - hDirACRend->num_outputs_dir = 2; /* Two channels are pre-rendered for stereo type detection */ + hDirAC->num_outputs_diff = 1; /* There is one output channel in mono */ + hDirAC->num_outputs_dir = 2; /* Two channels are pre-rendered for stereo type detection */ } else { @@ -335,135 +551,154 @@ static ivas_error ivas_dirac_rend_config( if ( flag_config == DIRAC_OPEN ) { - num_outputs_dir_old = hDirACRend->num_outputs_dir; - if ( ( hDirACRend->proto_index_dir = (int16_t *) malloc( sizeof( int16_t ) * hDirACRend->num_outputs_dir ) ) == NULL ) + num_outputs_dir_old = hDirAC->num_outputs_dir; + if ( ( hDirAC->proto_index_dir = (int16_t *) malloc( sizeof( int16_t ) * hDirAC->num_outputs_dir ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); } - num_outputs_diff_old = hDirACRend->num_outputs_diff; - if ( ( hDirACRend->proto_index_diff = (int16_t *) malloc( sizeof( int16_t ) * hDirACRend->num_outputs_diff ) ) == NULL ) + num_outputs_diff_old = hDirAC->num_outputs_diff; + if ( ( hDirAC->proto_index_diff = (int16_t *) malloc( sizeof( int16_t ) * hDirAC->num_outputs_diff ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); } } - if ( hDirACRend->num_outputs_dir != num_outputs_dir_old && flag_config == DIRAC_RECONFIGURE ) + if ( hDirAC->num_outputs_dir != num_outputs_dir_old && flag_config == DIRAC_RECONFIGURE ) { - free( hDirACRend->proto_index_dir ); - if ( ( hDirACRend->proto_index_dir = (int16_t *) malloc( sizeof( int16_t ) * hDirACRend->num_outputs_dir ) ) == NULL ) + free( hDirAC->proto_index_dir ); + if ( ( hDirAC->proto_index_dir = (int16_t *) malloc( sizeof( int16_t ) * hDirAC->num_outputs_dir ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); } } - set_s( hDirACRend->proto_index_dir, 0, hDirACRend->num_outputs_dir ); + set_s( hDirAC->proto_index_dir, 0, hDirAC->num_outputs_dir ); - if ( hDirACRend->num_outputs_diff != num_outputs_diff_old && flag_config == DIRAC_RECONFIGURE ) + if ( hDirAC->num_outputs_diff != num_outputs_diff_old && flag_config == DIRAC_RECONFIGURE ) { - free( hDirACRend->proto_index_diff ); - if ( ( hDirACRend->proto_index_diff = (int16_t *) malloc( sizeof( int16_t ) * hDirACRend->num_outputs_diff ) ) == NULL ) + free( hDirAC->proto_index_diff ); + if ( ( hDirAC->proto_index_diff = (int16_t *) malloc( sizeof( int16_t ) * hDirAC->num_outputs_diff ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); } } - set_s( hDirACRend->proto_index_diff, 0, hDirACRend->num_outputs_diff ); + set_s( hDirAC->proto_index_diff, 0, hDirAC->num_outputs_diff ); - hDirACRend->sba_map_tc = sba_map_tc; + hDirAC->sba_map_tc = sba_map_tc; if ( st_ivas->ivas_format == SBA_FORMAT ) { if ( st_ivas->sba_order > SBA_FOA_ORDER && ivas_total_brate >= IVAS_512k ) { - hDirACRend->sba_map_tc = sba_map_tc_512; + hDirAC->sba_map_tc = sba_map_tc_512; } } if ( nchan_transport == 1 ) { - hDirACRend->num_protos_ambi = 1; - hDirACRend->num_protos_dir = 1; - hDirACRend->num_protos_diff = 1; + hDirAC->num_protos_ambi = 1; + hDirAC->num_protos_dir = 1; + hDirAC->num_protos_diff = 1; + + if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) + { + hDirAC->num_protos_dir = 2; + hDirAC->num_protos_diff = 2; + hDirAC->proto_index_dir[0] = 0; + hDirAC->proto_index_dir[1] = 1; + hDirAC->proto_index_diff[0] = 0; + hDirAC->proto_index_diff[1] = 1; + } } else if ( nchan_transport == 2 ) { - if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) + if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) { - hDirACRend->num_protos_ambi = 2; - hDirACRend->num_protos_diff = 1; - hDirACRend->num_protos_dir = 2; - hDirACRend->proto_index_dir[1] = 1; + hDirAC->num_protos_ambi = 2; + hDirAC->num_protos_diff = 1; + hDirAC->num_protos_dir = 2; + hDirAC->proto_index_dir[1] = 1; } - else if ( hDirACRend->hOutSetup.output_config == AUDIO_CONFIG_MONO ) + else if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) + { + hDirAC->num_protos_dir = 2; + hDirAC->num_protos_diff = 2; + hDirAC->proto_index_dir[0] = 0; + hDirAC->proto_index_dir[1] = 1; + hDirAC->proto_index_diff[0] = 0; + hDirAC->proto_index_diff[1] = 1; + } + else if ( hDirAC->hOutSetup.output_config == AUDIO_CONFIG_MONO ) { /* Following the foa rendering for code compatibility */ - hDirACRend->num_protos_ambi = 2; - hDirACRend->num_protos_dir = 2; - hDirACRend->num_protos_diff = 3; - hDirACRend->proto_index_dir[0] = 0; - hDirACRend->proto_index_diff[0] = 0; + hDirAC->num_protos_ambi = 2; + hDirAC->num_protos_dir = 2; + hDirAC->num_protos_diff = 3; + hDirAC->proto_index_dir[0] = 0; + hDirAC->proto_index_diff[0] = 0; } else { - hDirACRend->num_protos_ambi = 2; - hDirACRend->num_protos_diff = 3; + hDirAC->num_protos_ambi = 2; + hDirAC->num_protos_diff = 3; - for ( k = 0; k < hDirACRend->num_outputs_diff; k++ ) + for ( k = 0; k < hDirAC->num_outputs_diff; k++ ) { if ( ls_azimuth[k] > 0.0f ) { - hDirACRend->proto_index_diff[k] = 1; + hDirAC->proto_index_diff[k] = 1; } else if ( ls_azimuth[k] < 0.0f ) { - hDirACRend->proto_index_diff[k] = 2; + hDirAC->proto_index_diff[k] = 2; } else { - hDirACRend->proto_index_diff[k] = 0; + hDirAC->proto_index_diff[k] = 0; } } - if ( hDirACRend->hOutSetup.is_loudspeaker_setup ) + if ( hDirAC->hOutSetup.is_loudspeaker_setup ) { - hDirACRend->num_protos_dir = 3; - mvs2s( hDirACRend->proto_index_diff, hDirACRend->proto_index_dir, nchan_out_woLFE ); + hDirAC->num_protos_dir = 3; + mvs2s( hDirAC->proto_index_diff, hDirAC->proto_index_dir, nchan_out_woLFE ); } else { - hDirACRend->num_protos_dir = 2; - hDirACRend->proto_index_dir[1] = 1; + hDirAC->num_protos_dir = 2; + hDirAC->proto_index_dir[1] = 1; } } } else /* nchan_transport > 2 */ { - hDirACRend->num_protos_ambi = 4; - if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_PSD_LS ) + hDirAC->num_protos_ambi = 4; + if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_PSD_LS ) { - hDirACRend->num_protos_diff = hDirACRend->num_outputs_diff; - for ( k = 0; k < hDirACRend->num_outputs_diff; k++ ) + hDirAC->num_protos_diff = hDirAC->num_outputs_diff; + for ( k = 0; k < hDirAC->num_outputs_diff; k++ ) { - hDirACRend->proto_index_diff[k] = k; + hDirAC->proto_index_diff[k] = k; } - hDirACRend->num_protos_dir = hDirACRend->num_outputs_dir; - for ( k = 0; k < hDirACRend->num_outputs_dir; k++ ) + hDirAC->num_protos_dir = hDirAC->num_outputs_dir; + for ( k = 0; k < hDirAC->num_outputs_dir; k++ ) { - hDirACRend->proto_index_dir[k] = k; + hDirAC->proto_index_dir[k] = k; } } else { - hDirACRend->num_protos_diff = 1; - hDirACRend->num_protos_dir = nchan_transport; - if ( ( st_ivas->sba_planar ) && ( !( st_ivas->ivas_format == SBA_FORMAT ) ) ) // Todo Dolby/FhG refactor: Is this ever true? + hDirAC->num_protos_diff = 1; + hDirAC->num_protos_dir = nchan_transport; + if ( ( st_ivas->sba_planar ) && ( !( st_ivas->ivas_format == SBA_FORMAT ) ) ) { - hDirACRend->num_protos_dir++; + hDirAC->num_protos_dir++; } - for ( k = 0; k < min( hDirACRend->num_outputs_dir, hDirACRend->num_protos_dir ); k++ ) + for ( k = 0; k < min( hDirAC->num_outputs_dir, hDirAC->num_protos_dir ); k++ ) { - if ( hDirACRend->sba_map_tc[k] < hDirACRend->num_outputs_dir ) + if ( hDirAC->sba_map_tc[k] < hDirAC->num_outputs_dir ) { - hDirACRend->proto_index_dir[hDirACRend->sba_map_tc[k]] = k; + hDirAC->proto_index_dir[hDirAC->sba_map_tc[k]] = k; } } } @@ -472,61 +707,61 @@ static ivas_error ivas_dirac_rend_config( /* direct/diffuse responses */ if ( flag_config == DIRAC_OPEN ) { - if ( ( hDirACRend->diffuse_response_function = (float *) malloc( sizeof( float ) * hDirACRend->num_outputs_dir ) ) == NULL ) + if ( ( hDirAC->diffuse_response_function = (float *) malloc( sizeof( float ) * hDirAC->num_outputs_dir ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); } } /* reallocate static memory */ - else if ( flag_config == DIRAC_RECONFIGURE && hDirACRend->num_outputs_dir != num_outputs_dir_old ) + else if ( flag_config == DIRAC_RECONFIGURE && hDirAC->num_outputs_dir != num_outputs_dir_old ) { - free( hDirACRend->diffuse_response_function ); - hDirACRend->diffuse_response_function = NULL; - if ( ( hDirACRend->diffuse_response_function = (float *) malloc( sizeof( float ) * hDirACRend->num_outputs_dir ) ) == NULL ) + free( hDirAC->diffuse_response_function ); + hDirAC->diffuse_response_function = NULL; + if ( ( hDirAC->diffuse_response_function = (float *) malloc( sizeof( float ) * hDirAC->num_outputs_dir ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); } } - if ( ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_PSD_LS ) || ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_PSD_SHD ) || ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_MONO ) ) + if ( ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_PSD_LS ) || ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_PSD_SHD ) || ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_MONO ) ) { - initDiffuseResponses( hDirACRend->diffuse_response_function, nchan_out_woLFE, hDirACRend->hOutSetup.output_config, - hDirACRend->hOutSetup, hDirACRend->hOutSetup.ambisonics_order, st_ivas->ivas_format, &hDirACRend->num_ele_spk_no_diffuse_rendering, st_ivas->transport_config ); + initDiffuseResponses( hDirAC->diffuse_response_function, nchan_out_woLFE, hDirAC->hOutSetup.output_config, + hDirAC->hOutSetup, hDirAC->hOutSetup.ambisonics_order, st_ivas->ivas_format, &hDirAC->num_ele_spk_no_diffuse_rendering, st_ivas->transport_config ); } else { - initDiffuseResponses( hDirACRend->diffuse_response_function, hDirACRend->num_outputs_dir, AUDIO_CONFIG_FOA, - hDirACRend->hOutSetup, hDirACRend->hOutSetup.ambisonics_order, st_ivas->ivas_format, &hDirACRend->num_ele_spk_no_diffuse_rendering, AUDIO_CONFIG_INVALID ); + initDiffuseResponses( hDirAC->diffuse_response_function, hDirAC->num_outputs_dir, AUDIO_CONFIG_FOA, + hDirAC->hOutSetup, hDirAC->hOutSetup.ambisonics_order, st_ivas->ivas_format, &hDirAC->num_ele_spk_no_diffuse_rendering, AUDIO_CONFIG_INVALID ); } - if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_PSD_SHD ) + if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_PSD_SHD ) { if ( flag_config == DIRAC_OPEN ) { - if ( ( hDirACRend->hoa_encoder = (float *) malloc( nchan_out_woLFE * hDirACRend->num_outputs_diff * sizeof( float ) ) ) == NULL ) + if ( ( hDirAC->hoa_encoder = (float *) malloc( nchan_out_woLFE * hDirAC->num_outputs_diff * sizeof( float ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); } } - else if ( flag_config == DIRAC_RECONFIGURE && hDirACRend->hoa_encoder && ( hDirACRend->num_outputs_diff != num_outputs_diff_old ) ) + else if ( flag_config == DIRAC_RECONFIGURE && hDirAC->hoa_encoder && ( hDirAC->num_outputs_diff != num_outputs_diff_old ) ) { - free( hDirACRend->hoa_encoder ); - hDirACRend->hoa_encoder = NULL; - if ( ( hDirACRend->hoa_encoder = (float *) malloc( nchan_out_woLFE * hDirACRend->num_outputs_diff * sizeof( float ) ) ) == NULL ) + free( hDirAC->hoa_encoder ); + hDirAC->hoa_encoder = NULL; + if ( ( hDirAC->hoa_encoder = (float *) malloc( nchan_out_woLFE * hDirAC->num_outputs_diff * sizeof( float ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); } } - set_f( hDirACRend->hoa_encoder, 0.0f, nchan_out_woLFE * hDirACRend->num_outputs_diff ); - compute_hoa_encoder_mtx( ls_azimuth, ls_elevation, hDirACRend->hoa_encoder, hDirACRend->num_outputs_diff, hDirACRend->hOutSetup.ambisonics_order ); + set_f( hDirAC->hoa_encoder, 0.0f, nchan_out_woLFE * hDirAC->num_outputs_diff ); + compute_hoa_encoder_mtx( ls_azimuth, ls_elevation, hDirAC->hoa_encoder, hDirAC->num_outputs_diff, hDirAC->hOutSetup.ambisonics_order ); } else { - if ( flag_config == DIRAC_RECONFIGURE && hDirACRend->hoa_encoder ) + if ( flag_config == DIRAC_RECONFIGURE && hDirAC->hoa_encoder ) { - free( hDirACRend->hoa_encoder ); + free( hDirAC->hoa_encoder ); } - hDirACRend->hoa_encoder = NULL; + hDirAC->hoa_encoder = NULL; } /* VBAP */ @@ -535,25 +770,32 @@ static ivas_error ivas_dirac_rend_config( st_ivas->hVBAPdata = NULL; } - if ( hDirACRend->panningConf == DIRAC_PANNING_VBAP ) + if ( hDirAC->panningConf == DIRAC_PANNING_VBAP ) { if ( flag_config == DIRAC_RECONFIGURE && st_ivas->hVBAPdata != NULL ) { vbap_free_data( &( st_ivas->hVBAPdata ) ); } +#ifdef MASA_AND_OBJECTS + if ( ( error = vbap_init_data( &( st_ivas->hVBAPdata ), ls_azimuth, ls_elevation, nchan_out_woLFE, st_ivas->ivas_format ) ) != IVAS_ERR_OK ) + { + return error; + } +#else if ( ( error = vbap_init_data( &( st_ivas->hVBAPdata ), ls_azimuth, ls_elevation, nchan_out_woLFE ) ) != IVAS_ERR_OK ) { return error; } +#endif } - else if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_MONO ) + else if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_MONO ) { if ( flag_config == DIRAC_RECONFIGURE && st_ivas->hVBAPdata != NULL ) { vbap_free_data( &( st_ivas->hVBAPdata ) ); } - hDirACRend->hoa_decoder = NULL; + hDirAC->hoa_decoder = NULL; } else if ( flag_config == DIRAC_RECONFIGURE && st_ivas->hVBAPdata != NULL ) { @@ -563,67 +805,67 @@ static ivas_error ivas_dirac_rend_config( /* HOA panning/dec */ if ( flag_config == DIRAC_OPEN ) { - hDirACRend->hoa_decoder = NULL; - if ( ( hDirACRend->panningConf == DIRAC_PANNING_HOA3 ) || st_ivas->ivas_format == SBA_FORMAT || ( nchan_transport > 2 ) ) + hDirAC->hoa_decoder = NULL; + if ( ( hDirAC->panningConf == DIRAC_PANNING_HOA3 ) || st_ivas->ivas_format == SBA_FORMAT || ( nchan_transport > 2 ) ) { - if ( hDirACRend->hOutSetup.is_loudspeaker_setup ) + if ( hDirAC->hOutSetup.is_loudspeaker_setup ) { if ( st_ivas->hoa_dec_mtx != NULL ) { free( st_ivas->hoa_dec_mtx ); st_ivas->hoa_dec_mtx = NULL; } - if ( ( error = ivas_sba_get_hoa_dec_matrix( hDirACRend->hOutSetup, &st_ivas->hoa_dec_mtx, hDirACRend->hOutSetup.ambisonics_order ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_sba_get_hoa_dec_matrix( hDirAC->hOutSetup, &st_ivas->hoa_dec_mtx, hDirAC->hOutSetup.ambisonics_order ) ) != IVAS_ERR_OK ) { return error; } - hDirACRend->hoa_decoder = st_ivas->hoa_dec_mtx; + hDirAC->hoa_decoder = st_ivas->hoa_dec_mtx; } } } /* decorrelation */ - proto_signal_decorr_on_old = ( flag_config == DIRAC_RECONFIGURE ) ? hDirACRend->proto_signal_decorr_on : 0; - hDirACRend->proto_signal_decorr_on = 1; - if ( ( nchan_transport > 2 ) && ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_PSD_LS ) ) + proto_signal_decorr_on_old = ( flag_config == DIRAC_RECONFIGURE ) ? hDirAC->proto_signal_decorr_on : 0; + hDirAC->proto_signal_decorr_on = 1; + if ( ( nchan_transport > 2 ) && ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_PSD_LS ) ) { /*switch off decorrelation for 4 transport channels*/ - hDirACRend->proto_signal_decorr_on = 0; + hDirAC->proto_signal_decorr_on = 0; } - if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_MONO ) + if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_MONO ) { - hDirACRend->proto_signal_decorr_on = 0; + hDirAC->proto_signal_decorr_on = 0; } - if ( ( flag_config == DIRAC_OPEN && hDirACRend->proto_signal_decorr_on ) || ( flag_config == DIRAC_RECONFIGURE && ( hDirACRend->proto_signal_decorr_on && !proto_signal_decorr_on_old ) ) ) + if ( ( flag_config == DIRAC_OPEN && hDirAC->proto_signal_decorr_on ) || ( flag_config == DIRAC_RECONFIGURE && ( hDirAC->proto_signal_decorr_on && !proto_signal_decorr_on_old ) ) ) { - if ( ( error = ivas_dirac_dec_decorr_open( &( hDirACRend->h_freq_domain_decorr_ap_params ), - &( hDirACRend->h_freq_domain_decorr_ap_state ), - hSpatParamRendCom->num_freq_bands, - hDirACRend->num_outputs_diff, - hDirACRend->num_protos_diff, - hDirACRend->synthesisConf, - hDirACRend->frequency_axis, + if ( ( error = ivas_dirac_dec_decorr_open( &( hDirAC->h_freq_domain_decorr_ap_params ), + &( hDirAC->h_freq_domain_decorr_ap_state ), + hDirAC->num_freq_bands, + hDirAC->num_outputs_diff, + hDirAC->num_protos_diff, + hDirAC->synthesisConf, + hDirAC->frequency_axis, nchan_transport > 2 ? 4 : nchan_transport, output_Fs ) ) != IVAS_ERR_OK ) { return error; } } - else if ( flag_config == DIRAC_RECONFIGURE && ( !hDirACRend->proto_signal_decorr_on && proto_signal_decorr_on_old ) ) + else if ( flag_config == DIRAC_RECONFIGURE && ( !hDirAC->proto_signal_decorr_on && proto_signal_decorr_on_old ) ) { - ivas_dirac_dec_decorr_close( &hDirACRend->h_freq_domain_decorr_ap_params, &hDirACRend->h_freq_domain_decorr_ap_state ); + ivas_dirac_dec_decorr_close( &hDirAC->h_freq_domain_decorr_ap_params, &hDirAC->h_freq_domain_decorr_ap_state ); } - else if ( flag_config == DIRAC_RECONFIGURE && hDirACRend->proto_signal_decorr_on && proto_signal_decorr_on_old ) + else if ( flag_config == DIRAC_RECONFIGURE && hDirAC->proto_signal_decorr_on && proto_signal_decorr_on_old ) { - if ( nchan_transport != nchan_transport_old || hDirACRend->num_outputs_diff != num_outputs_diff_old || flag_config_inp == DIRAC_RECONFIGURE_MODE ) + if ( nchan_transport != nchan_transport_old || hDirAC->num_outputs_diff != num_outputs_diff_old || flag_config_inp == DIRAC_RECONFIGURE_MODE ) { /* close and reopen the decorrelator */ - ivas_dirac_dec_decorr_close( &hDirACRend->h_freq_domain_decorr_ap_params, &hDirACRend->h_freq_domain_decorr_ap_state ); + ivas_dirac_dec_decorr_close( &hDirAC->h_freq_domain_decorr_ap_params, &hDirAC->h_freq_domain_decorr_ap_state ); - if ( ( error = ivas_dirac_dec_decorr_open( &( hDirACRend->h_freq_domain_decorr_ap_params ), &( hDirACRend->h_freq_domain_decorr_ap_state ), hSpatParamRendCom->num_freq_bands, hDirACRend->num_outputs_diff, - hDirACRend->num_protos_diff, hDirACRend->synthesisConf, hDirACRend->frequency_axis, nchan_transport > 2 ? 4 : nchan_transport, output_Fs ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_dirac_dec_decorr_open( &( hDirAC->h_freq_domain_decorr_ap_params ), &( hDirAC->h_freq_domain_decorr_ap_state ), hDirAC->num_freq_bands, hDirAC->num_outputs_diff, + hDirAC->num_protos_diff, hDirAC->synthesisConf, hDirAC->frequency_axis, nchan_transport > 2 ? 4 : nchan_transport, output_Fs ) ) != IVAS_ERR_OK ) { return error; } @@ -633,54 +875,54 @@ static ivas_error ivas_dirac_rend_config( /* output synthesis */ if ( flag_config == DIRAC_OPEN ) { - if ( ( ivas_dirac_dec_output_synthesis_open( hSpatParamRendCom, hDirACRend, st_ivas->renderer_type, nchan_transport, output_Fs, hodirac_flag ) ) != IVAS_ERR_OK ) + if ( ( ivas_dirac_dec_output_synthesis_open( hDirAC, st_ivas->renderer_type, nchan_transport, output_Fs, hodirac_flag ) ) != IVAS_ERR_OK ) { return error; } - hDirACRend->h_output_synthesis_psd_params.use_onset_filters = hDirACRend->proto_signal_decorr_on; + hDirAC->h_output_synthesis_psd_params.use_onset_filters = hDirAC->proto_signal_decorr_on; } - else if ( ( flag_config == DIRAC_RECONFIGURE ) && ( ( nchan_transport != nchan_transport_old ) || ( hDirACRend->num_outputs_diff != num_outputs_diff_old ) ) ) + else if ( ( flag_config == DIRAC_RECONFIGURE ) && ( ( nchan_transport != nchan_transport_old ) || ( hDirAC->num_outputs_diff != num_outputs_diff_old ) ) ) { - ivas_dirac_dec_output_synthesis_close( hDirACRend ); + ivas_dirac_dec_output_synthesis_close( hDirAC ); - if ( ( ivas_dirac_dec_output_synthesis_open( hSpatParamRendCom, hDirACRend, st_ivas->renderer_type, nchan_transport, output_Fs, hodirac_flag ) ) != IVAS_ERR_OK ) + if ( ( ivas_dirac_dec_output_synthesis_open( hDirAC, st_ivas->renderer_type, nchan_transport, output_Fs, hodirac_flag ) ) != IVAS_ERR_OK ) { return error; } - hDirACRend->h_output_synthesis_psd_params.use_onset_filters = hDirACRend->proto_signal_decorr_on; + hDirAC->h_output_synthesis_psd_params.use_onset_filters = hDirAC->proto_signal_decorr_on; } - if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_PSD_SHD || hDirACRend->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) + if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_PSD_SHD || hDirAC->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) { - hDirACRend->h_output_synthesis_psd_params.use_onset_filters = 0; + hDirAC->h_output_synthesis_psd_params.use_onset_filters = 0; } /*-----------------------------------------------------------------* * memory allocation *-----------------------------------------------------------------*/ - if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) + if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) { - if ( flag_config == DIRAC_RECONFIGURE && hDirACRend->proto_frame_f ) + if ( flag_config == DIRAC_RECONFIGURE && hDirAC->proto_frame_f ) { - free( hDirACRend->proto_frame_f ); + free( hDirAC->proto_frame_f ); } - hDirACRend->proto_frame_f = NULL; + hDirAC->proto_frame_f = NULL; } else { - if ( flag_config == DIRAC_OPEN || ( flag_config == DIRAC_RECONFIGURE && hDirACRend->proto_frame_f == NULL ) ) + if ( flag_config == DIRAC_OPEN || ( flag_config == DIRAC_RECONFIGURE && hDirAC->proto_frame_f == NULL ) ) { - if ( ( hDirACRend->proto_frame_f = (float *) malloc( sizeof( float ) * 2 * hDirACRend->num_protos_diff * hSpatParamRendCom->num_freq_bands ) ) == NULL ) + if ( ( hDirAC->proto_frame_f = (float *) malloc( sizeof( float ) * 2 * hDirAC->num_protos_diff * hDirAC->num_freq_bands ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); } } - else if ( flag_config == DIRAC_RECONFIGURE && ( hDirACRend->num_protos_diff != num_protos_diff_old ) ) + else if ( flag_config == DIRAC_RECONFIGURE && ( hDirAC->num_protos_diff != num_protos_diff_old ) ) { - proto_frame_f_old = hDirACRend->proto_frame_f; + proto_frame_f_old = hDirAC->proto_frame_f; free( proto_frame_f_old ); - if ( ( hDirACRend->proto_frame_f = (float *) malloc( sizeof( float ) * 2 * hDirACRend->num_protos_diff * hSpatParamRendCom->num_freq_bands ) ) == NULL ) + if ( ( hDirAC->proto_frame_f = (float *) malloc( sizeof( float ) * 2 * hDirAC->num_protos_diff * hDirAC->num_freq_bands ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); } @@ -690,31 +932,31 @@ static ivas_error ivas_dirac_rend_config( if ( flag_config == DIRAC_OPEN ) { - hDirACRend->buffer_energy = NULL; + hDirAC->buffer_energy = NULL; } if ( ( flag_config == DIRAC_OPEN && hDirAC->hConfig->dec_param_estim == TRUE ) || ( flag_config == DIRAC_RECONFIGURE && ( hDirAC->hConfig->dec_param_estim == TRUE && dec_param_estim_old == FALSE ) ) ) { - hDirACRend->index_buffer_intensity = 0; + hDirAC->index_buffer_intensity = 0; for ( i = 0; i < DIRAC_NUM_DIMS; i++ ) { for ( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ ) { - if ( ( hDirACRend->buffer_intensity_real[i][j] = (float *) malloc( CLDFB_NO_CHANNELS_MAX * sizeof( float ) ) ) == NULL ) + if ( ( hDirAC->buffer_intensity_real[i][j] = (float *) malloc( CLDFB_NO_CHANNELS_MAX * sizeof( float ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); } - set_f( hDirACRend->buffer_intensity_real[i][j], 0.0f, CLDFB_NO_CHANNELS_MAX ); + set_f( hDirAC->buffer_intensity_real[i][j], 0.0f, CLDFB_NO_CHANNELS_MAX ); } } - if ( hDirACRend->buffer_energy == NULL ) + if ( hDirAC->buffer_energy == NULL ) { - if ( ( hDirACRend->buffer_energy = (float *) malloc( DIRAC_NO_COL_AVG_DIFF * CLDFB_NO_CHANNELS_MAX * sizeof( float ) ) ) == NULL ) + if ( ( hDirAC->buffer_energy = (float *) malloc( DIRAC_NO_COL_AVG_DIFF * CLDFB_NO_CHANNELS_MAX * sizeof( float ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); } } - set_f( hDirACRend->buffer_energy, 0.0f, DIRAC_NO_COL_AVG_DIFF * CLDFB_NO_CHANNELS_MAX ); + set_f( hDirAC->buffer_energy, 0.0f, DIRAC_NO_COL_AVG_DIFF * CLDFB_NO_CHANNELS_MAX ); } else if ( ( flag_config == DIRAC_OPEN && hDirAC->hConfig->dec_param_estim == FALSE ) || ( flag_config == DIRAC_RECONFIGURE && ( hDirAC->hConfig->dec_param_estim == FALSE && dec_param_estim_old == TRUE ) ) ) { @@ -722,228 +964,132 @@ static ivas_error ivas_dirac_rend_config( { for ( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ ) { - if ( flag_config == DIRAC_RECONFIGURE && hDirACRend->buffer_intensity_real[i][j] ) + if ( flag_config == DIRAC_RECONFIGURE && hDirAC->buffer_intensity_real[i][j] ) { - free( hDirACRend->buffer_intensity_real[i][j] ); + free( hDirAC->buffer_intensity_real[i][j] ); } - hDirACRend->buffer_intensity_real[i][j] = NULL; + hDirAC->buffer_intensity_real[i][j] = NULL; } } - if ( hDirACRend->buffer_energy != NULL ) + if ( hDirAC->buffer_energy != NULL ) { - free( hDirACRend->buffer_energy ); - hDirACRend->buffer_energy = NULL; + free( hDirAC->buffer_energy ); + hDirAC->buffer_energy = NULL; } } /* output synthesis */ - ivas_dirac_dec_output_synthesis_init( hSpatParamRendCom, hDirACRend, nchan_out_woLFE, hodirac_flag ); + ivas_dirac_dec_output_synthesis_init( hDirAC, nchan_out_woLFE, hodirac_flag ); /* Allocate stack memory */ if ( flag_config != DIRAC_OPEN ) { - ivas_dirac_free_mem( &( hDirACRend->stack_mem ) ); + ivas_dirac_free_mem( &( hDirAC->stack_mem ) ); } - if ( ( error = ivas_dirac_alloc_mem( hDirACRend, st_ivas->renderer_type, hSpatParamRendCom->num_freq_bands, &( hDirACRend->stack_mem ), hodirac_flag ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_dirac_alloc_mem( hDirAC, st_ivas->renderer_type, &( hDirAC->stack_mem ), hodirac_flag ) ) != IVAS_ERR_OK ) { return error; } + mvs2s( DirAC_block_grouping, hDirAC->block_grouping, MAX_PARAM_SPATIAL_SUBFRAMES + 1 ); + if ( flag_config == DIRAC_OPEN ) { - st_ivas->hDirACRend = hDirACRend; - } - - return error; -} - - -/*------------------------------------------------------------------------- - * ivas_dirac_dec_config() - * - * Open or reconfigure decoder DirAC/MASA handle - *-------------------------------------------------------------------------*/ + hDirAC->dirac_md_buffer_length = 0; + hDirAC->dirac_bs_md_write_idx = 0; + hDirAC->dirac_read_idx = 0; + hDirAC->spar_to_dirac_write_idx = 0; + if ( st_ivas->mc_mode == MC_MODE_MCMASA ) + { + hDirAC->dirac_md_buffer_length = MAX_PARAM_SPATIAL_SUBFRAMES; -ivas_error ivas_dirac_dec_config( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ - const DIRAC_CONFIG_FLAG flag_config_inp /* i/ : Flag determining if we open or reconfigure the DirAC decoder */ -) -{ - ivas_error error; - int32_t output_Fs; - int16_t hodirac_flag; - int16_t sparfoa_flag; - DIRAC_CONFIG_FLAG dec_config_flag; - DIRAC_CONFIG_FLAG rend_config_flag; - DIRAC_CONFIG_FLAG common_rend_config_flag; - int16_t need_dirac_rend; - int16_t need_parambin; - int16_t dec_param_estim_old; - int16_t dec_param_estim_new; + set_s( hDirAC->render_to_md_map, 0, MAX_JBM_SUBFRAMES_5MS * JBM_CLDFB_SLOTS_IN_SUBFRAME ); + for ( map_idx = 0; map_idx < DEFAULT_JBM_SUBFRAMES_5MS; map_idx++ ) + { + hDirAC->render_to_md_map[map_idx] = map_idx; + } + } +#ifdef MASA_AND_OBJECTS + else if ( st_ivas->ivas_format == MASA_FORMAT || st_ivas->ivas_format == MASA_ISM_FORMAT ) +#else + else if ( st_ivas->ivas_format == MASA_FORMAT ) +#endif + { + hDirAC->dirac_md_buffer_length = MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR; + hDirAC->dirac_bs_md_write_idx = DELAY_MASA_PARAM_DEC_SFR; - error = IVAS_ERR_OK; + set_s( hDirAC->render_to_md_map, 0, MAX_JBM_SUBFRAMES_5MS * JBM_CLDFB_SLOTS_IN_SUBFRAME ); + for ( map_idx = 0; map_idx < DEFAULT_JBM_SUBFRAMES_5MS; map_idx++ ) + { + hDirAC->render_to_md_map[map_idx] = map_idx; + } + } + else + { + int16_t num_slots_in_subfr; + num_slots_in_subfr = hDirAC->hConfig->dec_param_estim ? CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES : 1; + hDirAC->dirac_md_buffer_length = ( MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_DIRAC_PARAM_DEC_SFR ); + hDirAC->dirac_bs_md_write_idx = DELAY_DIRAC_PARAM_DEC_SFR; + hDirAC->spar_to_dirac_write_idx = DELAY_DIRAC_PARAM_DEC_SFR; + hDirAC->dirac_read_idx = 0; + hDirAC->dirac_estimator_idx = 0; + + set_s( hDirAC->render_to_md_map, 0, MAX_JBM_SUBFRAMES_5MS * JBM_CLDFB_SLOTS_IN_SUBFRAME ); + for ( map_idx = 0; map_idx < DEFAULT_JBM_SUBFRAMES_5MS * num_slots_in_subfr; map_idx++ ) + { + hDirAC->render_to_md_map[map_idx] = hDirAC->dirac_read_idx + map_idx / num_slots_in_subfr; + } + } - /* Solve and setup flags for inits */ - dec_config_flag = ( flag_config_inp == DIRAC_RECONFIGURE_MODE ) ? DIRAC_RECONFIGURE : flag_config_inp; + if ( ( error = ivas_dirac_allocate_parameters( hDirAC, 1 ) ) != IVAS_ERR_OK ) + { + return error; + } - output_Fs = st_ivas->hDecoderConfig->output_Fs; - hodirac_flag = ivas_get_hodirac_flag( st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->sba_analysis_order ); - dec_param_estim_old = ( dec_config_flag == DIRAC_RECONFIGURE ) ? st_ivas->hDirAC->hConfig->dec_param_estim : FALSE; - - - sparfoa_flag = 0; - if ( st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_FOA && st_ivas->ivas_format == SBA_FORMAT && !hodirac_flag ) - { - sparfoa_flag = 1; - } - - if ( ( error = ivas_dirac_dec_config_internal( st_ivas, dec_config_flag ) ) != IVAS_ERR_OK ) - { - return error; - } - - /* This is required for parambin */ - if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) - { - st_ivas->hDirAC->hConfig->dec_param_estim = FALSE; - } - - dec_param_estim_new = st_ivas->hDirAC->hConfig->dec_param_estim; - - /* Setup renderers and meta */ - /* First, free everything if in reconfig and not the active renderer */ - need_parambin = 0; - switch ( st_ivas->renderer_type ) - { - case RENDERER_BINAURAL_PARAMETRIC: - case RENDERER_BINAURAL_PARAMETRIC_ROOM: - case RENDERER_STEREO_PARAMETRIC: - need_parambin = 1; - break; - default: - need_parambin = 0; - } - - if ( !need_parambin ) - { - ivas_dirac_dec_close_binaural_data( &st_ivas->hDiracDecBin ); - } - - need_dirac_rend = 0; - switch ( st_ivas->renderer_type ) - { - case RENDERER_DIRAC: - case RENDERER_BINAURAL_FASTCONV: - case RENDERER_BINAURAL_FASTCONV_ROOM: - case RENDERER_SBA_LINEAR_ENC: - case RENDERER_SBA_LINEAR_DEC: - need_dirac_rend = 1; - break; - default: - need_dirac_rend = 0; - } - - if ( !need_dirac_rend ) - { - ivas_dirac_rend_close( &st_ivas->hDirACRend ); - } - - if ( !sparfoa_flag ) - { - common_rend_config_flag = st_ivas->hSpatParamRendCom == NULL ? DIRAC_OPEN : flag_config_inp; - if ( ( error = ivas_spat_hSpatParamRendCom_config( &st_ivas->hSpatParamRendCom, common_rend_config_flag, dec_param_estim_new, - st_ivas->ivas_format, st_ivas->mc_mode, output_Fs, hodirac_flag ) ) != IVAS_ERR_OK ) - { - return error; - } - - if ( need_dirac_rend ) +#ifdef MASA_AND_OBJECTS + if ( st_ivas->ivas_format == MASA_FORMAT || st_ivas->ivas_format == MASA_ISM_FORMAT || ( st_ivas->ivas_format == SBA_FORMAT && st_ivas->hDecoderConfig->ivas_total_brate > IVAS_256k ) ) +#else + if ( st_ivas->ivas_format == MASA_FORMAT || ( st_ivas->ivas_format == SBA_FORMAT && st_ivas->hDecoderConfig->ivas_total_brate > IVAS_256k ) ) +#endif { - rend_config_flag = st_ivas->hDirACRend == NULL ? DIRAC_OPEN : flag_config_inp; - if ( ( error = ivas_dirac_rend_config( st_ivas, rend_config_flag, dec_param_estim_old ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_dirac_allocate_parameters( hDirAC, 2 ) ) != IVAS_ERR_OK ) { return error; } } - - if ( need_parambin ) + else { - if ( st_ivas->renderer_type != RENDERER_STEREO_PARAMETRIC ) - { - if ( ( error = ivas_dirac_dec_binaural_copy_hrtfs( &st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) - { - return error; - } - } - - if ( st_ivas->hDiracDecBin == NULL ) - { - if ( ( error = ivas_dirac_dec_init_binaural_data( st_ivas, st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) - { - return error; - } - } - else - { - /* This is required to keep BE in rate switching. This probably means that 1TC and 2TC MASA perform differently. */ - if ( st_ivas->hDiracDecBin->h_freq_domain_decorr_ap_params != NULL && !( st_ivas->ivas_format == MASA_FORMAT && st_ivas->nSCE > 0 ) ) - { - ivas_dirac_dec_decorr_close( &st_ivas->hDiracDecBin->h_freq_domain_decorr_ap_params, &st_ivas->hDiracDecBin->h_freq_domain_decorr_ap_state ); - } - - if ( ( error = ivas_td_decorr_reconfig_dec( st_ivas->ivas_format, st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->nchan_transport, st_ivas->hDecoderConfig->output_Fs, &( st_ivas->hDiracDecBin->hTdDecorr ), &( st_ivas->hDiracDecBin->useTdDecorr ) ) ) != IVAS_ERR_OK ) - { - return error; - } + hDirAC->azimuth2 = NULL; + hDirAC->elevation2 = NULL; + hDirAC->energy_ratio2 = NULL; + hDirAC->spreadCoherence2 = NULL; + } - if ( !st_ivas->hDiracDecBin->useTdDecorr ) - { - if ( st_ivas->hDiracDecBin->h_freq_domain_decorr_ap_params == NULL ) - { - float frequency_axis[CLDFB_NO_CHANNELS_MAX]; - ivas_dirac_dec_get_frequency_axis( frequency_axis, st_ivas->hDecoderConfig->output_Fs, st_ivas->hSpatParamRendCom->num_freq_bands ); - if ( ( error = ivas_dirac_dec_decorr_open( &( st_ivas->hDiracDecBin->h_freq_domain_decorr_ap_params ), - &( st_ivas->hDiracDecBin->h_freq_domain_decorr_ap_state ), - st_ivas->hSpatParamRendCom->num_freq_bands, - BINAURAL_CHANNELS, - BINAURAL_CHANNELS, - DIRAC_SYNTHESIS_PSD_LS, - frequency_axis, - BINAURAL_CHANNELS, - st_ivas->hDecoderConfig->output_Fs ) ) != IVAS_ERR_OK ) - { - return error; - } - } - } + hDirAC->hDiffuseDist = NULL; /* Memory is allocated from stack during runtime when needed */ - st_ivas->hDiracDecBin->reqularizationFactor = configure_reqularization_factor( st_ivas->ivas_format, st_ivas->hDecoderConfig->ivas_total_brate ); - } - } + hDirAC->dithering_seed = DIRAC_DITH_SEED; + st_ivas->hDirAC = hDirAC; } - /* Allocate transport channel buffers for SBA format when in JBM */ - if ( dec_config_flag == DIRAC_OPEN ) + /* allocate transport channels*/ + if ( flag_config == DIRAC_OPEN ) { if ( st_ivas->hDecoderConfig->voip_active == 1 && st_ivas->hTcBuffer == NULL ) { if ( st_ivas->ivas_format == SBA_FORMAT ) { int16_t nchan_to_allocate; - int16_t nchan_transport; - - nchan_transport = st_ivas->nchan_transport; nchan_to_allocate = nchan_transport; - if ( st_ivas->nchan_transport == 1 && ( ( st_ivas->renderer_type == RENDERER_DIRAC && st_ivas->hDirACRend->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) || ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) ) + if ( st_ivas->nchan_transport == 1 && ( ( st_ivas->renderer_type == RENDERER_DIRAC && st_ivas->hDirAC->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) || ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) ) { nchan_to_allocate++; /* we need a channel for the CNG in this case*/ } - if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) + if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) { nchan_to_allocate = 2 * BINAURAL_CHANNELS; } - if ( ( error = ivas_jbm_dec_tc_buffer_open( st_ivas, TC_BUFFER_MODE_RENDERER, nchan_transport, nchan_to_allocate, nchan_to_allocate, st_ivas->hSpatParamRendCom->slot_size ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_jbm_dec_tc_buffer_open( st_ivas, TC_BUFFER_MODE_RENDERER, nchan_transport, nchan_to_allocate, nchan_to_allocate, hDirAC->slot_size ) ) != IVAS_ERR_OK ) { return error; } @@ -962,8 +1108,10 @@ ivas_error ivas_dirac_dec_config( *------------------------------------------------------------------------*/ void ivas_dirac_dec_close( - DIRAC_DEC_HANDLE *hDirAC_out ) + DIRAC_DEC_HANDLE *hDirAC_out /* i/o: decoder DirAC handle */ +) { + int16_t i, j; DIRAC_DEC_HANDLE hDirAC; if ( hDirAC_out == NULL || *hDirAC_out == NULL ) @@ -980,6 +1128,86 @@ void ivas_dirac_dec_close( hDirAC->hConfig = NULL; } + /* close Output synthesis sub-module */ + ivas_dirac_dec_output_synthesis_close( hDirAC ); + + /* close Decorrelator sub-module */ + if ( hDirAC->proto_signal_decorr_on ) + { + ivas_dirac_dec_decorr_close( &hDirAC->h_freq_domain_decorr_ap_params, &hDirAC->h_freq_domain_decorr_ap_state ); + } + + /* Params */ + + /* free frequency axis buffer */ + if ( hDirAC->frequency_axis != NULL ) + { + free( hDirAC->frequency_axis ); + hDirAC->frequency_axis = NULL; + } + + if ( hDirAC->diffuse_response_function != NULL ) + { + free( hDirAC->diffuse_response_function ); + hDirAC->diffuse_response_function = NULL; + } + + if ( hDirAC->hoa_encoder != NULL ) + { + free( hDirAC->hoa_encoder ); + hDirAC->hoa_encoder = NULL; + } + + /* prototype indexing */ + if ( hDirAC->proto_index_dir != NULL ) + { + free( hDirAC->proto_index_dir ); + hDirAC->proto_index_dir = NULL; + } + + if ( hDirAC->proto_index_diff != NULL ) + { + free( hDirAC->proto_index_diff ); + hDirAC->proto_index_dir = NULL; + } + + /* States */ + + /* free prototype signal buffers */ + if ( hDirAC->proto_frame_f != NULL ) + { + free( hDirAC->proto_frame_f ); + hDirAC->proto_frame_f = NULL; + } + + for ( i = 0; i < DIRAC_NUM_DIMS; i++ ) + { + for ( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ ) + { + if ( hDirAC->buffer_intensity_real[i][j] != NULL ) + { + free( hDirAC->buffer_intensity_real[i][j] ); + hDirAC->buffer_intensity_real[i][j] = NULL; + } + } + } + if ( hDirAC->buffer_energy != NULL ) + { + free( hDirAC->buffer_energy ); + hDirAC->buffer_energy = NULL; + } + + ivas_dirac_deallocate_parameters( hDirAC, 1 ); + ivas_dirac_deallocate_parameters( hDirAC, 2 ); + + if ( hDirAC->masa_stereo_type_detect != NULL ) + { + free( hDirAC->masa_stereo_type_detect ); + hDirAC->masa_stereo_type_detect = NULL; + } + + ivas_dirac_free_mem( &( hDirAC->stack_mem ) ); + free( *hDirAC_out ); *hDirAC_out = NULL; @@ -988,557 +1216,2019 @@ void ivas_dirac_dec_close( /*------------------------------------------------------------------------- - * ivas_dirac_dec_read_BS() + * ivas_dirac_deallocate_parameters() * - * Read DirAC parameters from the bitstream - *------------------------------------------------------------------------*/ + * Deallocate DirAC parameters + *-------------------------------------------------------------------------*/ -void ivas_dirac_dec_read_BS( - const int32_t ivas_total_brate, /* i : IVAS total bitrate */ - Decoder_State *st, /* i/o: decoder state structure */ - DIRAC_DEC_HANDLE hDirAC, /* i/o: decoder DirAC handle */ - SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, /* i/o: common spatial rendering data handle */ - IVAS_QMETADATA_HANDLE hQMetaData, /* i/o: q_metadata */ - int16_t *nb_bits, /* o : number of bits read */ - const int16_t hodirac_flag, /* i : flag to indicate HO-DirAC mode */ - int16_t *dirac_to_spar_md_bands /* o : DirAC->SPAR MD bands */ +void ivas_dirac_deallocate_parameters( + DIRAC_DEC_HANDLE hDirAC, /* i/o: decoder DirAC handle */ + const int16_t params_flag /* i : set of parameters flag */ ) { - int16_t i, j, b, dir, orig_dirac_bands; - int16_t next_bit_pos_orig; - *nb_bits = 0; - if ( !st->bfi && ivas_total_brate > IVAS_SID_5k2 ) - { - next_bit_pos_orig = st->next_bit_pos; - st->next_bit_pos = (int16_t) ( ivas_total_brate / FRAMES_PER_SEC - 1 ); - - /* 1 bit flag for signaling metadata to read */ - b = st->bit_stream[( st->next_bit_pos )--]; - ( *nb_bits )++; + int16_t i; - if ( b == 1 ) /* WB 4TCs condition, no other metadata to read*/ + if ( params_flag == 1 ) + { + if ( hDirAC->azimuth != NULL ) { - orig_dirac_bands = hQMetaData->q_direction[0].cfg.nbands; + for ( i = 0; i < hDirAC->dirac_md_buffer_length; i++ ) + { + if ( hDirAC->azimuth[i] != NULL ) + { + free( hDirAC->azimuth[i] ); + hDirAC->azimuth[i] = NULL; + } + } - hQMetaData->sba_inactive_mode = 1; + free( hDirAC->azimuth ); + hDirAC->azimuth = NULL; + } - /* if we start with a SID frame, we need to init the azi/ele arrays.*/ - if ( st->ini_frame == 0 ) + if ( hDirAC->elevation != NULL ) + { + for ( i = 0; i < hDirAC->dirac_md_buffer_length; i++ ) { - for ( b = 0; b < hQMetaData->q_direction[0].cfg.nbands; b++ ) + if ( hDirAC->elevation[i] != NULL ) { - set_zero( hQMetaData->q_direction[0].band_data[b].azimuth, MAX_PARAM_SPATIAL_SUBFRAMES ); - set_zero( hQMetaData->q_direction[0].band_data[b].elevation, MAX_PARAM_SPATIAL_SUBFRAMES ); + free( hDirAC->elevation[i] ); + hDirAC->elevation[i] = NULL; } } - *nb_bits += ivas_qmetadata_dec_sid_decode( hQMetaData, st->bit_stream, &( st->next_bit_pos ), 0, NULL, SBA_FORMAT ); - for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ ) + free( hDirAC->elevation ); + hDirAC->elevation = NULL; + } + + if ( hDirAC->energy_ratio1 != NULL ) + { + for ( i = 0; i < hDirAC->dirac_md_buffer_length; i++ ) { - hQMetaData->q_direction[0].band_data[orig_dirac_bands - 1].azimuth[i] = hQMetaData->q_direction[0].band_data[1].azimuth[0]; - hQMetaData->q_direction[0].band_data[orig_dirac_bands - 1].elevation[i] = hQMetaData->q_direction[0].band_data[1].elevation[0]; - hQMetaData->q_direction[0].band_data[orig_dirac_bands - 1].energy_ratio[i] = hQMetaData->q_direction[0].band_data[1].energy_ratio[0]; + if ( hDirAC->energy_ratio1[i] != NULL ) + { + free( hDirAC->energy_ratio1[i] ); + hDirAC->energy_ratio1[i] = NULL; + } } - for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ ) + free( hDirAC->energy_ratio1 ); + hDirAC->energy_ratio1 = NULL; + } + + if ( hDirAC->diffuseness_vector != NULL ) + { + for ( i = 0; i < hDirAC->dirac_md_buffer_length; i++ ) { - for ( j = orig_dirac_bands - 2; j >= 0; j-- ) + if ( hDirAC->diffuseness_vector[i] != NULL ) { - hQMetaData->q_direction[0].band_data[j].azimuth[i] = hQMetaData->q_direction[0].band_data[0].azimuth[0]; - hQMetaData->q_direction[0].band_data[j].elevation[i] = hQMetaData->q_direction[0].band_data[0].elevation[0]; - hQMetaData->q_direction[0].band_data[j].energy_ratio[i] = hQMetaData->q_direction[0].band_data[0].energy_ratio[0]; + free( hDirAC->diffuseness_vector[i] ); + hDirAC->diffuseness_vector[i] = NULL; } } - hQMetaData->q_direction->cfg.nbands = orig_dirac_bands; + free( hDirAC->diffuseness_vector ); + hDirAC->diffuseness_vector = NULL; } - else + + if ( hDirAC->spreadCoherence != NULL ) { - hQMetaData->sba_inactive_mode = 0; - hQMetaData->is_masa_ivas_format = 0; - if ( hQMetaData->useLowerRes ) + for ( i = 0; i < hDirAC->dirac_md_buffer_length; i++ ) { - hQMetaData->q_direction[0].cfg.nblocks = 1; + if ( hDirAC->spreadCoherence[i] != NULL ) + { + free( hDirAC->spreadCoherence[i] ); + hDirAC->spreadCoherence[i] = NULL; + } } - else + free( hDirAC->spreadCoherence ); + hDirAC->spreadCoherence = NULL; + } + + if ( hDirAC->surroundingCoherence != NULL ) + { + for ( i = 0; i < hDirAC->dirac_md_buffer_length; i++ ) { - hQMetaData->q_direction[0].cfg.nblocks = MAX_PARAM_SPATIAL_SUBFRAMES; + if ( hDirAC->surroundingCoherence[i] != NULL ) + { + free( hDirAC->surroundingCoherence[i] ); + hDirAC->surroundingCoherence[i] = NULL; + } } - - *nb_bits += ivas_qmetadata_dec_decode( hQMetaData, st->bit_stream, &( st->next_bit_pos ), hodirac_flag ); + free( hDirAC->surroundingCoherence ); + hDirAC->surroundingCoherence = NULL; } - -#ifdef DEBUGGING - assert( *nb_bits >= 0 ); -#endif - - st->next_bit_pos = next_bit_pos_orig; } - else if ( !st->bfi && ivas_total_brate == IVAS_SID_5k2 ) + else if ( params_flag == 2 ) { - next_bit_pos_orig = st->next_bit_pos; - - /* subtract mode signaling bits, since bitstream was moved after mode reading */ - st->next_bit_pos = (int16_t) ( ivas_total_brate / FRAMES_PER_SEC - 1 - SID_FORMAT_NBITS ); -#ifndef SBA_MODE_CLEANUP_2 - /* 1 bit flag for SPAR/DirAC, already read in read format function */ -#else - /* 1 bit flag for signaling metadata to read */ -#endif - b = st->bit_stream[( st->next_bit_pos )--]; - ( *nb_bits )++; - hQMetaData->sba_inactive_mode = 1; - orig_dirac_bands = hQMetaData->q_direction[0].cfg.nbands; - - /* if we start with a SID frame, we need to init the azi/ele arrays.*/ - if ( st->ini_frame == 0 ) + if ( hDirAC->azimuth2 != NULL ) { - for ( dir = 0; dir < hQMetaData->no_directions; dir++ ) + for ( i = 0; i < hDirAC->dirac_md_buffer_length; i++ ) { - for ( b = 0; b < hQMetaData->q_direction[dir].cfg.nbands; b++ ) + if ( hDirAC->azimuth2[i] != NULL ) { - set_zero( hQMetaData->q_direction[dir].band_data[b].azimuth, MAX_PARAM_SPATIAL_SUBFRAMES ); - set_zero( hQMetaData->q_direction[dir].band_data[b].elevation, MAX_PARAM_SPATIAL_SUBFRAMES ); + free( hDirAC->azimuth2[i] ); + hDirAC->azimuth2[i] = NULL; } } + free( hDirAC->azimuth2 ); + hDirAC->azimuth2 = NULL; } - *nb_bits += ivas_qmetadata_dec_sid_decode( hQMetaData, st->bit_stream, &( st->next_bit_pos ), 0, NULL, SBA_FORMAT ); - for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ ) + if ( hDirAC->elevation2 != NULL ) { - hQMetaData->q_direction[0].band_data[orig_dirac_bands - 1].azimuth[i] = hQMetaData->q_direction[0].band_data[1].azimuth[0]; - hQMetaData->q_direction[0].band_data[orig_dirac_bands - 1].elevation[i] = hQMetaData->q_direction[0].band_data[1].elevation[0]; - hQMetaData->q_direction[0].band_data[orig_dirac_bands - 1].energy_ratio[i] = hQMetaData->q_direction[0].band_data[1].energy_ratio[0]; + for ( i = 0; i < hDirAC->dirac_md_buffer_length; i++ ) + { + if ( hDirAC->elevation2[i] != NULL ) + { + free( hDirAC->elevation2[i] ); + hDirAC->elevation2[i] = NULL; + } + } + free( hDirAC->elevation2 ); + hDirAC->elevation2 = NULL; } - for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ ) + + if ( hDirAC->energy_ratio2 != NULL ) { - for ( j = orig_dirac_bands - 2; j >= 0; j-- ) + for ( i = 0; i < hDirAC->dirac_md_buffer_length; i++ ) { - hQMetaData->q_direction[0].band_data[j].azimuth[i] = hQMetaData->q_direction[0].band_data[0].azimuth[0]; - hQMetaData->q_direction[0].band_data[j].elevation[i] = hQMetaData->q_direction[0].band_data[0].elevation[0]; - hQMetaData->q_direction[0].band_data[j].energy_ratio[i] = hQMetaData->q_direction[0].band_data[0].energy_ratio[0]; + if ( hDirAC->energy_ratio2[i] != NULL ) + { + free( hDirAC->energy_ratio2[i] ); + hDirAC->energy_ratio2[i] = NULL; + } } + free( hDirAC->energy_ratio2 ); + hDirAC->energy_ratio2 = NULL; } - hQMetaData->q_direction->cfg.nbands = orig_dirac_bands; - - st->next_bit_pos = next_bit_pos_orig; - } - - if ( hDirAC != NULL && hSpatParamRendCom != NULL ) - { - ivas_qmetadata_to_dirac( hQMetaData, hDirAC, NULL, hSpatParamRendCom, ivas_total_brate, SBA_FORMAT, hodirac_flag, dirac_to_spar_md_bands ); + if ( hDirAC->spreadCoherence2 != NULL ) + { + for ( i = 0; i < hDirAC->dirac_md_buffer_length; i++ ) + { + if ( hDirAC->spreadCoherence2[i] != NULL ) + { + free( hDirAC->spreadCoherence2[i] ); + hDirAC->spreadCoherence2[i] = NULL; + } + } + free( hDirAC->spreadCoherence2 ); + hDirAC->spreadCoherence2 = NULL; + } } return; } -/*-----------------------------------------------------------------------* - * ivas_qmetadata_to_dirac() +/*------------------------------------------------------------------------- + * ivas_dirac_alloc_mem() * - * Copy qmetedata to DirAC parameters for rendering - *-----------------------------------------------------------------------*/ + * Allocate stack memory for DirAC renderer + *------------------------------------------------------------------------*/ -void ivas_qmetadata_to_dirac( - const IVAS_QMETADATA_HANDLE hQMetaData, /* i : frame of MASA q_metadata */ - DIRAC_DEC_HANDLE hDirAC, /* i : DirAC decoder structure */ - MASA_DECODER_HANDLE hMasa, /* i : MASA decoder structure */ - SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, /* i/o: common spatial renderer data handle */ - const int32_t ivas_total_brate, /* i : IVAS total bitrate */ - const IVAS_FORMAT ivas_format, /* i : IVAS format */ - const int16_t hodirac_flag, /* i : flag to indicate HO-DirAC mode */ - int16_t *dirac_to_spar_md_bands /* o : DirAC->SPAR MD bands */ -) +static ivas_error ivas_dirac_alloc_mem( + DIRAC_DEC_HANDLE hDirAC, + const RENDERER_TYPE renderer_type, + DIRAC_DEC_STACK_MEM_HANDLE hDirAC_mem, + const int16_t hodirac_flag ) { - int16_t block, band; - int16_t *seed_ptr; - int16_t band_start, band_end, diff_idx; - float diffuseness; - int16_t b, ele, azi; - float azimuth, elevation; - IVAS_QDIRECTION *q_direction; - int16_t *band_mapping; - int16_t *band_grouping; - int16_t start_band; - int16_t nbands = 0; - int16_t nblocks = 0; - int16_t qBand_idx; - int16_t idx_sec = 0; - int16_t no_secs = 1; + int16_t num_freq_bands, num_freq_bands_diff, size; + int16_t size_ho; + int16_t size_pf; + int16_t num_outputs_dir, num_outputs_diff; + int16_t num_protos_dir; - q_direction = &( hQMetaData->q_direction[0] ); - hSpatParamRendCom->numSimultaneousDirections = hQMetaData->no_directions; + num_protos_dir = hDirAC->num_protos_dir; - if ( hMasa != NULL && ivas_total_brate > IVAS_SID_5k2 ) - { - int16_t meta_write_index; - band_mapping = hMasa->data.band_mapping; - - for ( block = 0; block < MAX_PARAM_SPATIAL_SUBFRAMES; ++block ) - { - meta_write_index = ( hSpatParamRendCom->dirac_bs_md_write_idx + block ) % hSpatParamRendCom->dirac_md_buffer_length; + num_freq_bands = hDirAC->num_freq_bands; + num_freq_bands_diff = hDirAC->h_output_synthesis_psd_params.max_band_decorr; - for ( band = 0; band < hMasa->config.numCodingBands; ++band ) - { - for ( b = MASA_band_grouping_24[band_mapping[band]]; b < MASA_band_grouping_24[band_mapping[band + 1]]; ++b ) - { - hSpatParamRendCom->azimuth[meta_write_index][b] = (int16_t) q_direction->band_data[band].azimuth[block]; - hSpatParamRendCom->elevation[meta_write_index][b] = (int16_t) q_direction->band_data[band].elevation[block]; - hSpatParamRendCom->energy_ratio1[meta_write_index][b] = q_direction->band_data[band].energy_ratio[block]; - hSpatParamRendCom->diffuseness_vector[meta_write_index][b] = 1.0f - q_direction->band_data[band].energy_ratio[block]; + num_outputs_dir = hDirAC->num_outputs_dir; + num_outputs_diff = hDirAC->num_outputs_diff; - if ( q_direction->coherence_band_data != NULL ) - { - hSpatParamRendCom->spreadCoherence[meta_write_index][b] = q_direction->coherence_band_data[band].spread_coherence[block] / 255.0f; - } - else - { - hSpatParamRendCom->spreadCoherence[meta_write_index][b] = 0.0f; - } + size = num_freq_bands * num_outputs_dir; + if ( hodirac_flag ) + { + size_ho = size * DIRAC_HO_NUMSECTORS; + size_pf = num_freq_bands * DIRAC_HO_NUMSECTORS; + } + else + { + size_ho = size; + size_pf = num_freq_bands; + } - if ( hQMetaData->surcoh_band_data != NULL ) - { - hSpatParamRendCom->surroundingCoherence[meta_write_index][b] = hQMetaData->surcoh_band_data[band].surround_coherence[block] / 255.0f; - } - else - { - hSpatParamRendCom->surroundingCoherence[meta_write_index][b] = 0.0f; - } - } - } + /* PSD related buffers */ + hDirAC_mem->cy_auto_dir_smooth = NULL; + hDirAC_mem->proto_power_smooth = NULL; + hDirAC_mem->proto_power_diff_smooth = NULL; + hDirAC_mem->direct_responses_square = NULL; + hDirAC_mem->frame_dec_f = NULL; + if ( hDirAC->synthesisConf != DIRAC_SYNTHESIS_GAIN_SHD ) + { + if ( ( hDirAC_mem->cy_auto_dir_smooth = (float *) malloc( sizeof( float ) * size ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); } + set_zero( hDirAC_mem->cy_auto_dir_smooth, size ); - if ( hQMetaData->no_directions == 2 ) + if ( ( hDirAC_mem->proto_power_smooth = (float *) malloc( sizeof( float ) * size ) ) == NULL ) { - q_direction = &( hQMetaData->q_direction[1] ); - for ( block = 0; block < MAX_PARAM_SPATIAL_SUBFRAMES; ++block ) - { - meta_write_index = ( hSpatParamRendCom->dirac_bs_md_write_idx + block ) % hSpatParamRendCom->dirac_md_buffer_length; + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); + } + set_zero( hDirAC_mem->proto_power_smooth, size ); - for ( band = 0; band < hMasa->config.numCodingBands; ++band ) - { - for ( b = MASA_band_grouping_24[band_mapping[band]]; b < MASA_band_grouping_24[band_mapping[band + 1]]; ++b ) - { - hSpatParamRendCom->azimuth2[meta_write_index][b] = (int16_t) q_direction->band_data[band].azimuth[block]; - hSpatParamRendCom->elevation2[meta_write_index][b] = (int16_t) q_direction->band_data[band].elevation[block]; - hSpatParamRendCom->energy_ratio2[meta_write_index][b] = q_direction->band_data[band].energy_ratio[block]; - hSpatParamRendCom->diffuseness_vector[meta_write_index][b] -= q_direction->band_data[band].energy_ratio[block]; + if ( ( hDirAC_mem->proto_power_diff_smooth = (float *) malloc( sizeof( float ) * size ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); + } + set_zero( hDirAC_mem->proto_power_diff_smooth, size ); - if ( q_direction->coherence_band_data != NULL ) - { - hSpatParamRendCom->spreadCoherence2[meta_write_index][b] = q_direction->coherence_band_data[band].spread_coherence[block] / 255.0f; - } - else - { - hSpatParamRendCom->spreadCoherence2[meta_write_index][b] = 0.0f; - } - } - } - } + if ( ( hDirAC_mem->direct_responses_square = (float *) malloc( sizeof( float ) * size ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); } - else if ( hSpatParamRendCom->azimuth2 != NULL && hSpatParamRendCom->elevation2 != NULL && hSpatParamRendCom->energy_ratio2 != NULL && hSpatParamRendCom->spreadCoherence2 != NULL ) + set_zero( hDirAC_mem->direct_responses_square, size ); + if ( hDirAC->proto_signal_decorr_on && ( renderer_type != RENDERER_BINAURAL_PARAMETRIC && renderer_type != RENDERER_BINAURAL_PARAMETRIC_ROOM && renderer_type != RENDERER_STEREO_PARAMETRIC ) ) { - /* zero out old dir2 data */ - for ( block = 0; block < MAX_PARAM_SPATIAL_SUBFRAMES; ++block ) + if ( ( hDirAC_mem->frame_dec_f = (float *) malloc( sizeof( float ) * 2 * num_outputs_diff * num_freq_bands ) ) == NULL ) { - meta_write_index = ( hSpatParamRendCom->dirac_bs_md_write_idx + block ) % hSpatParamRendCom->dirac_md_buffer_length; - set_s( hSpatParamRendCom->azimuth2[meta_write_index], 0, hSpatParamRendCom->num_freq_bands ); - set_s( hSpatParamRendCom->elevation2[meta_write_index], 0, hSpatParamRendCom->num_freq_bands ); - set_zero( hSpatParamRendCom->energy_ratio2[meta_write_index], hSpatParamRendCom->num_freq_bands ); - set_zero( hSpatParamRendCom->spreadCoherence2[meta_write_index], hSpatParamRendCom->num_freq_bands ); + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); } } } - else /* SBA mode/SID/Zero frame*/ + hDirAC->h_output_synthesis_psd_state.proto_power_smooth = hDirAC_mem->proto_power_smooth; + hDirAC->h_output_synthesis_psd_state.proto_power_diff_smooth = hDirAC_mem->proto_power_diff_smooth; + hDirAC->h_output_synthesis_psd_state.cy_auto_dir_smooth = hDirAC_mem->cy_auto_dir_smooth; + hDirAC->h_output_synthesis_psd_state.direct_responses_square = hDirAC_mem->direct_responses_square; + + /* Target and smoothed nrg factors/gains */ + if ( ( hDirAC_mem->cy_cross_dir_smooth = (float *) malloc( sizeof( float ) * size_ho ) ) == NULL ) { - int16_t tmp_write_idx_param_band; - int16_t tmp_write_idx_band; - float diffuseness_sec = 0.f; + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); + } + set_zero( hDirAC_mem->cy_cross_dir_smooth, size ); - /* ungroup */ - seed_ptr = &hDirAC->dithering_seed; - nblocks = q_direction->cfg.nblocks; - nbands = hDirAC->band_grouping[hDirAC->hConfig->nbands]; - band_grouping = hDirAC->band_grouping; + if ( hDirAC->synthesisConf != DIRAC_SYNTHESIS_GAIN_SHD ) + { + if ( ( hDirAC_mem->cy_auto_diff_smooth = (float *) malloc( sizeof( float ) * size ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); + } + set_zero( hDirAC_mem->cy_auto_diff_smooth, size ); + } + else + { + if ( ( hDirAC_mem->cy_auto_diff_smooth = (float *) malloc( sizeof( float ) * num_outputs_diff * num_freq_bands_diff ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); + } + set_zero( hDirAC_mem->cy_auto_diff_smooth, num_outputs_diff * num_freq_bands_diff ); + } + hDirAC->h_output_synthesis_psd_state.cy_cross_dir_smooth = hDirAC_mem->cy_cross_dir_smooth; + hDirAC->h_output_synthesis_psd_state.cy_auto_diff_smooth = hDirAC_mem->cy_auto_diff_smooth; - if ( ivas_total_brate <= IVAS_SID_5k2 && ivas_format != SBA_FORMAT ) + /*Responses (gains/factors)*/ + if ( ( hDirAC_mem->direct_responses = (float *) malloc( sizeof( float ) * size_ho ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); + } + set_zero( hDirAC_mem->direct_responses, size ); + + + hDirAC->h_output_synthesis_psd_state.direct_responses = hDirAC_mem->direct_responses; + + /* Prototypes */ + hDirAC_mem->proto_direct_buffer_f = NULL; + hDirAC_mem->proto_diffuse_buffer_f = NULL; + if ( renderer_type != RENDERER_BINAURAL_PARAMETRIC && renderer_type != RENDERER_BINAURAL_PARAMETRIC_ROOM && renderer_type != RENDERER_STEREO_PARAMETRIC ) + { + if ( ( hDirAC_mem->proto_direct_buffer_f = (float *) malloc( sizeof( float ) * 2 * MAX_PARAM_SPATIAL_SUBFRAMES * num_protos_dir * num_freq_bands ) ) == NULL ) { - /* SID/zero-frame: 1 direction, 5 bands, nblocks re-generated out of SID decoder*/ - start_band = 0; - hDirAC->hConfig->nbands = 5; - ivas_dirac_config_bands( hDirAC->band_grouping, hDirAC->hConfig->nbands, nbands, NULL, 0, 0, NULL ); - nbands = 5; + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); } - else + + if ( hDirAC->proto_signal_decorr_on ) { - start_band = hDirAC->hConfig->enc_param_start_band; - if ( ivas_format == SBA_FORMAT ) + if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_PSD_SHD ) { - hDirAC->hConfig->nbands = IVAS_MAX_NUM_BANDS; + if ( ( hDirAC_mem->proto_diffuse_buffer_f = (float *) malloc( sizeof( float ) * 2 * MAX_PARAM_SPATIAL_SUBFRAMES * size ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); + } } else { - hDirAC->hConfig->nbands = q_direction->cfg.nbands; + if ( ( hDirAC_mem->proto_diffuse_buffer_f = (float *) malloc( sizeof( float ) * 2 * MAX_PARAM_SPATIAL_SUBFRAMES * num_outputs_diff * num_freq_bands ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); + } } + } + } + hDirAC->h_output_synthesis_psd_state.proto_direct_buffer_f = hDirAC_mem->proto_direct_buffer_f; + hDirAC->h_output_synthesis_psd_state.proto_diffuse_buffer_f = hDirAC_mem->proto_diffuse_buffer_f; - ivas_dirac_config_bands( hDirAC->band_grouping, hDirAC->hConfig->nbands, nbands, dirac_to_spar_md_bands, hQMetaData->useLowerBandRes, hDirAC->hConfig->enc_param_start_band, hDirAC->hFbMdft ); + /* Gains/power factors*/ + hDirAC_mem->direct_power_factor = NULL; + hDirAC_mem->diffuse_power_factor = NULL; - nbands = hDirAC->hConfig->nbands; - if ( hQMetaData->q_direction[0].cfg.nblocks == 0 ) - { - /* No transmission -> no copy from qmetadata buffers*/ - nbands = start_band; - } + if ( renderer_type != RENDERER_BINAURAL_PARAMETRIC && renderer_type != RENDERER_BINAURAL_PARAMETRIC_ROOM && renderer_type != RENDERER_STEREO_PARAMETRIC ) + { + if ( ( hDirAC_mem->direct_power_factor = (float *) malloc( sizeof( float ) * size_pf ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); } - - /* Low-Bands with no spatial data transmitted, analysis at decoder side */ - for ( band = 0; band < start_band; band++ ) + if ( ( hDirAC_mem->diffuse_power_factor = (float *) malloc( sizeof( float ) * size_pf ) ) == NULL ) { - band_start = band_grouping[band]; - band_end = band_grouping[band + 1]; - tmp_write_idx_param_band = hSpatParamRendCom->dirac_bs_md_write_idx; + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); + } + } - for ( block = 0; block < MAX_PARAM_SPATIAL_SUBFRAMES; block++ ) + hDirAC->h_output_synthesis_psd_state.direct_power_factor = hDirAC_mem->direct_power_factor; + hDirAC->h_output_synthesis_psd_state.diffuse_power_factor = hDirAC_mem->diffuse_power_factor; + + hDirAC_mem->reference_power = NULL; + hDirAC_mem->onset_filter = NULL; + if ( hDirAC->synthesisConf != DIRAC_SYNTHESIS_GAIN_SHD ) + { + if ( renderer_type != RENDERER_BINAURAL_PARAMETRIC && renderer_type != RENDERER_BINAURAL_PARAMETRIC_ROOM && renderer_type != RENDERER_STEREO_PARAMETRIC ) + { + if ( ( hDirAC_mem->reference_power = (float *) malloc( sizeof( float ) * 2 * num_freq_bands ) ) == NULL ) { - for ( b = band_start; b < band_end; b++ ) + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); + } + if ( hDirAC->proto_signal_decorr_on ) + { + if ( ( hDirAC_mem->onset_filter = (float *) malloc( sizeof( float ) * num_outputs_diff * num_freq_bands ) ) == NULL ) { - tmp_write_idx_band = tmp_write_idx_param_band; - hSpatParamRendCom->spreadCoherence[block][b] = 0.0f; - hSpatParamRendCom->surroundingCoherence[block][b] = 0.0f; - - hSpatParamRendCom->elevation[tmp_write_idx_band][b] = 0; - hSpatParamRendCom->azimuth[tmp_write_idx_band][b] = 0; - hSpatParamRendCom->diffuseness_vector[tmp_write_idx_band][b] = 0.f; - - hSpatParamRendCom->spreadCoherence[tmp_write_idx_band][b] = 0.0f; - hSpatParamRendCom->surroundingCoherence[tmp_write_idx_band][b] = 0.0f; - hSpatParamRendCom->energy_ratio1[tmp_write_idx_band][b] = 0; - tmp_write_idx_band = ( tmp_write_idx_band + 1 ) % hSpatParamRendCom->dirac_md_buffer_length; + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); } } } - - /* Bands with spatial data transmitted */ - if ( hodirac_flag ) + } + else + { + if ( num_protos_dir > 2 ) { - no_secs = DIRAC_HO_NUMSECTORS; + if ( ( hDirAC_mem->reference_power = (float *) malloc( sizeof( float ) * 5 * num_freq_bands ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); + } } - for ( idx_sec = 0; idx_sec < no_secs; idx_sec++ ) + if ( hDirAC->proto_signal_decorr_on ) { - for ( band = start_band; band < nbands; band++ ) + if ( ( hDirAC_mem->onset_filter = (float *) malloc( sizeof( float ) * 2 * num_freq_bands ) ) == NULL ) { - band_start = band_grouping[band]; - band_end = band_grouping[band + 1]; - tmp_write_idx_param_band = hSpatParamRendCom->dirac_bs_md_write_idx; + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); + } + } + } - if ( ivas_format == SBA_FORMAT ) - { - qBand_idx = dirac_to_spar_md_bands[band] - start_band; - } - else - { - qBand_idx = band; - } - diffuseness = 1.0f - q_direction->band_data[qBand_idx].energy_ratio[0]; -#ifdef DEBUG_MODE_DIRAC - dbgwrite( &diffuseness, sizeof( float ), 1, 1, "./res/dirac_dec_diffuseness.dat" ); -#endif - diff_idx = q_direction->band_data[qBand_idx].energy_ratio_index[0]; + return IVAS_ERR_OK; +} - for ( block = 0; block < MAX_PARAM_SPATIAL_SUBFRAMES; block++ ) - { - int16_t block_qmetadata; - block_qmetadata = min( block, nblocks - 1 ); - block_qmetadata = max( block_qmetadata, 0 ); +static void ivas_dirac_free_mem( + DIRAC_DEC_STACK_MEM_HANDLE hDirAC_mem ) +{ + if ( hDirAC_mem->cy_auto_dir_smooth != NULL ) + { + free( hDirAC_mem->cy_auto_dir_smooth ); + } + if ( hDirAC_mem->proto_power_smooth != NULL ) + { + free( hDirAC_mem->proto_power_smooth ); + } + if ( hDirAC_mem->proto_power_diff_smooth != NULL ) + { + free( hDirAC_mem->proto_power_diff_smooth ); + } + if ( hDirAC_mem->direct_responses_square != NULL ) + { + free( hDirAC_mem->direct_responses_square ); + } + if ( hDirAC_mem->frame_dec_f != NULL ) + { + free( hDirAC_mem->frame_dec_f ); + } + if ( hDirAC_mem->cy_cross_dir_smooth != NULL ) + { + free( hDirAC_mem->cy_cross_dir_smooth ); + } + if ( hDirAC_mem->cy_auto_diff_smooth != NULL ) + { + free( hDirAC_mem->cy_auto_diff_smooth ); + } + if ( hDirAC_mem->direct_responses != NULL ) + { + free( hDirAC_mem->direct_responses ); + } + if ( hDirAC_mem->proto_direct_buffer_f != NULL ) + { + free( hDirAC_mem->proto_direct_buffer_f ); + } + if ( hDirAC_mem->proto_diffuse_buffer_f != NULL ) + { + free( hDirAC_mem->proto_diffuse_buffer_f ); + } + if ( hDirAC_mem->direct_power_factor != NULL ) + { + free( hDirAC_mem->direct_power_factor ); + } + if ( hDirAC_mem->diffuse_power_factor != NULL ) + { + free( hDirAC_mem->diffuse_power_factor ); + } + if ( hDirAC_mem->reference_power != NULL ) + { + free( hDirAC_mem->reference_power ); + } + if ( hDirAC_mem->onset_filter != NULL ) + { + free( hDirAC_mem->onset_filter ); + } - if ( q_direction[idx_sec].band_data[qBand_idx].azimuth[block_qmetadata] < 0.f ) - { - q_direction[idx_sec].band_data[qBand_idx].azimuth[block_qmetadata] += 360.f; - } + return; +} - if ( hMasa == NULL && hodirac_flag ) - { - azimuth = q_direction[idx_sec].band_data[qBand_idx].azimuth[block_qmetadata]; - elevation = q_direction[idx_sec].band_data[qBand_idx].elevation[block_qmetadata]; - diffuseness = 1.f - q_direction[0].band_data[qBand_idx].energy_ratio[block_qmetadata]; - diffuseness_sec = q_direction[1].band_data[qBand_idx].energy_ratio[block_qmetadata]; - assert( diffuseness_sec < 1.0001f && diffuseness_sec > -0.0001f ); - } - else - { - azimuth = q_direction->band_data[qBand_idx].azimuth[block_qmetadata]; - elevation = q_direction->band_data[qBand_idx].elevation[block_qmetadata]; - } - for ( b = band_start; b < band_end; b++ ) - { - tmp_write_idx_band = tmp_write_idx_param_band; +/*------------------------------------------------------------------------- + * ivas_dirac_dec_read_BS() + * + * Read DirAC parameters from the bitstream + *------------------------------------------------------------------------*/ - if ( hodirac_flag ) - { - azi = (int16_t) ( azimuth + 0.5f ); - ele = (int16_t) ( elevation + 0.5f ); - } - else - { - azi = (int16_t) ( azimuth + rand_triangular_signed( seed_ptr ) * dirac_dithering_azi_scale[diff_idx] + 0.5f ); - ele = (int16_t) ( elevation + rand_triangular_signed( seed_ptr ) * dirac_dithering_ele_scale[diff_idx] + 0.5f ); - /* limit the elevation to [-90, 90] */ - ele = min( 90, ele ); - ele = max( -90, ele ); - } +void ivas_dirac_dec_read_BS( + const int32_t ivas_total_brate, /* i : IVAS total bitrate */ + Decoder_State *st, /* i/o: decoder state structure */ + DIRAC_DEC_HANDLE hDirAC, /* i/o: decoder DirAC handle */ + IVAS_QMETADATA_HANDLE hQMetaData, /* i/o: q_metadata */ + int16_t *nb_bits, /* o : number of bits read */ + const int16_t hodirac_flag, /* i : flag to indicate HO-DirAC mode */ + int16_t *dirac_to_spar_md_bands /* o : DirAC->SPAR MD bands */ +) +{ + int16_t i, j, b, dir, orig_dirac_bands; + int16_t next_bit_pos_orig; + *nb_bits = 0; + if ( !st->bfi && ivas_total_brate > IVAS_SID_5k2 ) + { + next_bit_pos_orig = st->next_bit_pos; + st->next_bit_pos = (int16_t) ( ivas_total_brate / FRAMES_PER_SEC - 1 ); - if ( ivas_total_brate > IVAS_SID_5k2 && q_direction->coherence_band_data != NULL ) - { - hSpatParamRendCom->spreadCoherence[tmp_write_idx_band][b] = q_direction->coherence_band_data[qBand_idx].spread_coherence[block] / 255.0f; - } - else - { - hSpatParamRendCom->spreadCoherence[tmp_write_idx_band][b] = 0.0f; - } + /* 1 bit flag for signaling metadata to read */ + b = st->bit_stream[( st->next_bit_pos )--]; + ( *nb_bits )++; - if ( ivas_total_brate > IVAS_SID_5k2 && q_direction->coherence_band_data != NULL ) - { - hSpatParamRendCom->surroundingCoherence[tmp_write_idx_band][b] = hQMetaData->surcoh_band_data[qBand_idx].surround_coherence[0] / 255.0f; - } - else - { - hSpatParamRendCom->surroundingCoherence[tmp_write_idx_band][b] = 0.0f; - } + if ( b == 1 ) /* WB 4TCs condition, no other metadata to read*/ + { + orig_dirac_bands = hQMetaData->q_direction[0].cfg.nbands; - hSpatParamRendCom->energy_ratio1[tmp_write_idx_band][b] = q_direction->band_data[qBand_idx].energy_ratio[0]; + hQMetaData->sba_inactive_mode = 1; - hSpatParamRendCom->diffuseness_vector[tmp_write_idx_band][b] = diffuseness; + /* if we start with a SID frame, we need to init the azi/ele arrays.*/ + if ( st->ini_frame == 0 ) + { + for ( b = 0; b < hQMetaData->q_direction[0].cfg.nbands; b++ ) + { + set_zero( hQMetaData->q_direction[0].band_data[b].azimuth, MAX_PARAM_SPATIAL_SUBFRAMES ); + set_zero( hQMetaData->q_direction[0].band_data[b].elevation, MAX_PARAM_SPATIAL_SUBFRAMES ); + } + } + + *nb_bits += ivas_qmetadata_dec_sid_decode( hQMetaData, st->bit_stream, &( st->next_bit_pos ), 0, NULL, SBA_FORMAT ); + for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ ) + { + hQMetaData->q_direction[0].band_data[orig_dirac_bands - 1].azimuth[i] = hQMetaData->q_direction[0].band_data[1].azimuth[0]; + hQMetaData->q_direction[0].band_data[orig_dirac_bands - 1].elevation[i] = hQMetaData->q_direction[0].band_data[1].elevation[0]; + hQMetaData->q_direction[0].band_data[orig_dirac_bands - 1].energy_ratio[i] = hQMetaData->q_direction[0].band_data[1].energy_ratio[0]; + } + for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ ) + { + for ( j = orig_dirac_bands - 2; j >= 0; j-- ) + { + hQMetaData->q_direction[0].band_data[j].azimuth[i] = hQMetaData->q_direction[0].band_data[0].azimuth[0]; + hQMetaData->q_direction[0].band_data[j].elevation[i] = hQMetaData->q_direction[0].band_data[0].elevation[0]; + hQMetaData->q_direction[0].band_data[j].energy_ratio[i] = hQMetaData->q_direction[0].band_data[0].energy_ratio[0]; + } + } + + hQMetaData->q_direction->cfg.nbands = orig_dirac_bands; + } + else + { + hQMetaData->sba_inactive_mode = 0; + hQMetaData->is_masa_ivas_format = 0; + if ( hQMetaData->useLowerRes ) + { + hQMetaData->q_direction[0].cfg.nblocks = 1; + } + else + { + hQMetaData->q_direction[0].cfg.nblocks = MAX_PARAM_SPATIAL_SUBFRAMES; + } + + *nb_bits += ivas_qmetadata_dec_decode( hQMetaData, st->bit_stream, &( st->next_bit_pos ), hodirac_flag ); + } + +#ifdef DEBUGGING + assert( *nb_bits >= 0 ); +#endif + + st->next_bit_pos = next_bit_pos_orig; + } + else if ( !st->bfi && ivas_total_brate == IVAS_SID_5k2 ) + { + next_bit_pos_orig = st->next_bit_pos; + + /* subtract mode signaling bits, since bitstream was moved after mode reading */ + st->next_bit_pos = (int16_t) ( ivas_total_brate / FRAMES_PER_SEC - 1 - SID_FORMAT_NBITS ); +#ifndef SBA_MODE_CLEANUP_2 + /* 1 bit flag for SPAR/DirAC, already read in read format function */ +#else + /* 1 bit flag for signaling metadata to read */ +#endif + b = st->bit_stream[( st->next_bit_pos )--]; + ( *nb_bits )++; + hQMetaData->sba_inactive_mode = 1; + orig_dirac_bands = hQMetaData->q_direction[0].cfg.nbands; + + /* if we start with a SID frame, we need to init the azi/ele arrays.*/ + if ( st->ini_frame == 0 ) + { + for ( dir = 0; dir < hQMetaData->no_directions; dir++ ) + { + for ( b = 0; b < hQMetaData->q_direction[dir].cfg.nbands; b++ ) + { + set_zero( hQMetaData->q_direction[dir].band_data[b].azimuth, MAX_PARAM_SPATIAL_SUBFRAMES ); + set_zero( hQMetaData->q_direction[dir].band_data[b].elevation, MAX_PARAM_SPATIAL_SUBFRAMES ); + } + } + } + + *nb_bits += ivas_qmetadata_dec_sid_decode( hQMetaData, st->bit_stream, &( st->next_bit_pos ), 0, NULL, SBA_FORMAT ); + for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ ) + { + hQMetaData->q_direction[0].band_data[orig_dirac_bands - 1].azimuth[i] = hQMetaData->q_direction[0].band_data[1].azimuth[0]; + hQMetaData->q_direction[0].band_data[orig_dirac_bands - 1].elevation[i] = hQMetaData->q_direction[0].band_data[1].elevation[0]; + hQMetaData->q_direction[0].band_data[orig_dirac_bands - 1].energy_ratio[i] = hQMetaData->q_direction[0].band_data[1].energy_ratio[0]; + } + for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ ) + { + for ( j = orig_dirac_bands - 2; j >= 0; j-- ) + { + hQMetaData->q_direction[0].band_data[j].azimuth[i] = hQMetaData->q_direction[0].band_data[0].azimuth[0]; + hQMetaData->q_direction[0].band_data[j].elevation[i] = hQMetaData->q_direction[0].band_data[0].elevation[0]; + hQMetaData->q_direction[0].band_data[j].energy_ratio[i] = hQMetaData->q_direction[0].band_data[0].energy_ratio[0]; + } + } + + hQMetaData->q_direction->cfg.nbands = orig_dirac_bands; + + st->next_bit_pos = next_bit_pos_orig; + } + + if ( hDirAC != NULL ) + { + ivas_qmetadata_to_dirac( hQMetaData, hDirAC, NULL, ivas_total_brate, SBA_FORMAT, hodirac_flag, dirac_to_spar_md_bands ); + } + + return; +} + + +/*-----------------------------------------------------------------------* + * ivas_qmetadata_to_dirac() + * + * Copy qmetedata to DirAC parameters for rendering + *-----------------------------------------------------------------------*/ + +void ivas_qmetadata_to_dirac( + const IVAS_QMETADATA_HANDLE hQMetaData, /* i : frame of MASA q_metadata */ + DIRAC_DEC_HANDLE hDirAC, /* o : DirAC decoder structure */ + MASA_DECODER_HANDLE hMasa, /* i : MASA decoder structure */ + const int32_t ivas_total_brate, /* i : IVAS total bitrate */ + const IVAS_FORMAT ivas_format, /* i : IVAS format */ + const int16_t hodirac_flag, /* i : flag to indicate HO-DirAC mode */ + int16_t *dirac_to_spar_md_bands /* o : DirAC->SPAR MD bands */ +) +{ + int16_t block, band; + int16_t *seed_ptr; + int16_t band_start, band_end, diff_idx; + float diffuseness; + int16_t b, ele, azi; + float azimuth, elevation; + IVAS_QDIRECTION *q_direction; + int16_t *band_mapping; + int16_t *band_grouping; + int16_t start_band; + int16_t nbands = 0; + int16_t nblocks = 0; + int16_t qBand_idx; + int16_t idx_sec = 0; + int16_t no_secs = 1; + + q_direction = &( hQMetaData->q_direction[0] ); +#ifdef MASA_AND_OBJECTS + hDirAC->numParametricDirections = hQMetaData->no_directions; + hDirAC->numSimultaneousDirections = hDirAC->numParametricDirections + hDirAC->numIsmDirections; +#else + hDirAC->numSimultaneousDirections = hQMetaData->no_directions; +#endif + + if ( hMasa != NULL && ivas_total_brate > IVAS_SID_5k2 ) + { + int16_t meta_write_index; + band_mapping = hMasa->data.band_mapping; + + for ( block = 0; block < MAX_PARAM_SPATIAL_SUBFRAMES; ++block ) + { + meta_write_index = ( hDirAC->dirac_bs_md_write_idx + block ) % hDirAC->dirac_md_buffer_length; + + for ( band = 0; band < hMasa->config.numCodingBands; ++band ) + { + for ( b = MASA_band_grouping_24[band_mapping[band]]; b < MASA_band_grouping_24[band_mapping[band + 1]]; ++b ) + { + hDirAC->azimuth[meta_write_index][b] = (int16_t) q_direction->band_data[band].azimuth[block]; + hDirAC->elevation[meta_write_index][b] = (int16_t) q_direction->band_data[band].elevation[block]; + hDirAC->energy_ratio1[meta_write_index][b] = q_direction->band_data[band].energy_ratio[block]; + hDirAC->diffuseness_vector[meta_write_index][b] = 1.0f - q_direction->band_data[band].energy_ratio[block]; + + if ( q_direction->coherence_band_data != NULL ) + { + hDirAC->spreadCoherence[meta_write_index][b] = q_direction->coherence_band_data[band].spread_coherence[block] / 255.0f; + } + else + { + hDirAC->spreadCoherence[meta_write_index][b] = 0.0f; + } + + if ( hQMetaData->surcoh_band_data != NULL ) + { + hDirAC->surroundingCoherence[meta_write_index][b] = hQMetaData->surcoh_band_data[band].surround_coherence[block] / 255.0f; + } + else + { + hDirAC->surroundingCoherence[meta_write_index][b] = 0.0f; + } + } + } + } + + if ( hQMetaData->no_directions == 2 ) + { + q_direction = &( hQMetaData->q_direction[1] ); + for ( block = 0; block < MAX_PARAM_SPATIAL_SUBFRAMES; ++block ) + { + meta_write_index = ( hDirAC->dirac_bs_md_write_idx + block ) % hDirAC->dirac_md_buffer_length; + + for ( band = 0; band < hMasa->config.numCodingBands; ++band ) + { + for ( b = MASA_band_grouping_24[band_mapping[band]]; b < MASA_band_grouping_24[band_mapping[band + 1]]; ++b ) + { + hDirAC->azimuth2[meta_write_index][b] = (int16_t) q_direction->band_data[band].azimuth[block]; + hDirAC->elevation2[meta_write_index][b] = (int16_t) q_direction->band_data[band].elevation[block]; + hDirAC->energy_ratio2[meta_write_index][b] = q_direction->band_data[band].energy_ratio[block]; + hDirAC->diffuseness_vector[meta_write_index][b] -= q_direction->band_data[band].energy_ratio[block]; + + if ( q_direction->coherence_band_data != NULL ) + { + hDirAC->spreadCoherence2[meta_write_index][b] = q_direction->coherence_band_data[band].spread_coherence[block] / 255.0f; + } + else + { + hDirAC->spreadCoherence2[meta_write_index][b] = 0.0f; + } + } + } + } + } + else if ( hDirAC->azimuth2 != NULL && hDirAC->elevation2 != NULL && hDirAC->energy_ratio2 != NULL && hDirAC->spreadCoherence2 != NULL ) + { + /* zero out old dir2 data */ + for ( block = 0; block < MAX_PARAM_SPATIAL_SUBFRAMES; ++block ) + { + meta_write_index = ( hDirAC->dirac_bs_md_write_idx + block ) % hDirAC->dirac_md_buffer_length; + set_s( hDirAC->azimuth2[meta_write_index], 0, hDirAC->num_freq_bands ); + set_s( hDirAC->elevation2[meta_write_index], 0, hDirAC->num_freq_bands ); + set_zero( hDirAC->energy_ratio2[meta_write_index], hDirAC->num_freq_bands ); + set_zero( hDirAC->spreadCoherence2[meta_write_index], hDirAC->num_freq_bands ); + } + } + } + else /* SBA mode/SID/Zero frame*/ + { + int16_t tmp_write_idx_param_band; + int16_t tmp_write_idx_band; + float diffuseness_sec = 0.f; + + /* ungroup */ + seed_ptr = &hDirAC->dithering_seed; + nblocks = q_direction->cfg.nblocks; + nbands = hDirAC->band_grouping[hDirAC->hConfig->nbands]; + band_grouping = hDirAC->band_grouping; + + if ( ivas_total_brate <= IVAS_SID_5k2 && ivas_format != SBA_FORMAT ) + { + /* SID/zero-frame: 1 direction, 5 bands, nblocks re-generated out of SID decoder*/ + start_band = 0; + hDirAC->hConfig->nbands = 5; + ivas_dirac_config_bands( hDirAC->band_grouping, hDirAC->hConfig->nbands, nbands, NULL, 0, 0, NULL ); + nbands = 5; + } + else + { + start_band = hDirAC->hConfig->enc_param_start_band; + if ( ivas_format == SBA_FORMAT ) + { + hDirAC->hConfig->nbands = IVAS_MAX_NUM_BANDS; + } + else + { + hDirAC->hConfig->nbands = q_direction->cfg.nbands; + } + + ivas_dirac_config_bands( hDirAC->band_grouping, hDirAC->hConfig->nbands, nbands, dirac_to_spar_md_bands, hQMetaData->useLowerBandRes, hDirAC->hConfig->enc_param_start_band, hDirAC->hFbMdft ); + + nbands = hDirAC->hConfig->nbands; + if ( hQMetaData->q_direction[0].cfg.nblocks == 0 ) + { + /* No transmission -> no copy from qmetadata buffers*/ + nbands = start_band; + } + } + + /* Low-Bands with no spatial data transmitted, analysis at decoder side */ + for ( band = 0; band < start_band; band++ ) + { + band_start = band_grouping[band]; + band_end = band_grouping[band + 1]; + tmp_write_idx_param_band = hDirAC->dirac_bs_md_write_idx; + + for ( block = 0; block < MAX_PARAM_SPATIAL_SUBFRAMES; block++ ) + { + for ( b = band_start; b < band_end; b++ ) + { + tmp_write_idx_band = tmp_write_idx_param_band; + hDirAC->spreadCoherence[block][b] = 0.0f; + hDirAC->surroundingCoherence[block][b] = 0.0f; + + hDirAC->elevation[tmp_write_idx_band][b] = 0; + hDirAC->azimuth[tmp_write_idx_band][b] = 0; + hDirAC->diffuseness_vector[tmp_write_idx_band][b] = 0.f; + + hDirAC->spreadCoherence[tmp_write_idx_band][b] = 0.0f; + hDirAC->surroundingCoherence[tmp_write_idx_band][b] = 0.0f; + hDirAC->energy_ratio1[tmp_write_idx_band][b] = 0; + tmp_write_idx_band = ( tmp_write_idx_band + 1 ) % hDirAC->dirac_md_buffer_length; + } + } + } + + /* Bands with spatial data transmitted */ + if ( hodirac_flag ) + { + no_secs = DIRAC_HO_NUMSECTORS; + } + + for ( idx_sec = 0; idx_sec < no_secs; idx_sec++ ) + { + for ( band = start_band; band < nbands; band++ ) + { + band_start = band_grouping[band]; + band_end = band_grouping[band + 1]; + tmp_write_idx_param_band = hDirAC->dirac_bs_md_write_idx; + + if ( ivas_format == SBA_FORMAT ) + { + qBand_idx = dirac_to_spar_md_bands[band] - start_band; + } + else + { + qBand_idx = band; + } + diffuseness = 1.0f - q_direction->band_data[qBand_idx].energy_ratio[0]; +#ifdef DEBUG_MODE_DIRAC + dbgwrite( &diffuseness, sizeof( float ), 1, 1, "./res/dirac_dec_diffuseness.dat" ); +#endif + diff_idx = q_direction->band_data[qBand_idx].energy_ratio_index[0]; + + for ( block = 0; block < MAX_PARAM_SPATIAL_SUBFRAMES; block++ ) + { + int16_t block_qmetadata; + + block_qmetadata = min( block, nblocks - 1 ); + block_qmetadata = max( block_qmetadata, 0 ); + + if ( q_direction[idx_sec].band_data[qBand_idx].azimuth[block_qmetadata] < 0.f ) + { + q_direction[idx_sec].band_data[qBand_idx].azimuth[block_qmetadata] += 360.f; + } + + if ( hMasa == NULL && hodirac_flag ) + { + azimuth = q_direction[idx_sec].band_data[qBand_idx].azimuth[block_qmetadata]; + elevation = q_direction[idx_sec].band_data[qBand_idx].elevation[block_qmetadata]; + diffuseness = 1.f - q_direction[0].band_data[qBand_idx].energy_ratio[block_qmetadata]; + diffuseness_sec = q_direction[1].band_data[qBand_idx].energy_ratio[block_qmetadata]; + assert( diffuseness_sec < 1.0001f && diffuseness_sec > -0.0001f ); + } + else + { + azimuth = q_direction->band_data[qBand_idx].azimuth[block_qmetadata]; + elevation = q_direction->band_data[qBand_idx].elevation[block_qmetadata]; + } + + for ( b = band_start; b < band_end; b++ ) + { + tmp_write_idx_band = tmp_write_idx_param_band; + + if ( hodirac_flag ) + { + azi = (int16_t) ( azimuth + 0.5f ); + ele = (int16_t) ( elevation + 0.5f ); + } + else + { + azi = (int16_t) ( azimuth + rand_triangular_signed( seed_ptr ) * dirac_dithering_azi_scale[diff_idx] + 0.5f ); + ele = (int16_t) ( elevation + rand_triangular_signed( seed_ptr ) * dirac_dithering_ele_scale[diff_idx] + 0.5f ); + /* limit the elevation to [-90, 90] */ + ele = min( 90, ele ); + ele = max( -90, ele ); + } + + if ( ivas_total_brate > IVAS_SID_5k2 && q_direction->coherence_band_data != NULL ) + { + hDirAC->spreadCoherence[tmp_write_idx_band][b] = q_direction->coherence_band_data[qBand_idx].spread_coherence[block] / 255.0f; + } + else + { + hDirAC->spreadCoherence[tmp_write_idx_band][b] = 0.0f; + } + + if ( ivas_total_brate > IVAS_SID_5k2 && q_direction->coherence_band_data != NULL ) + { + hDirAC->surroundingCoherence[tmp_write_idx_band][b] = hQMetaData->surcoh_band_data[qBand_idx].surround_coherence[0] / 255.0f; + } + else + { + hDirAC->surroundingCoherence[tmp_write_idx_band][b] = 0.0f; + } + + hDirAC->energy_ratio1[tmp_write_idx_band][b] = q_direction->band_data[qBand_idx].energy_ratio[0]; + + hDirAC->diffuseness_vector[tmp_write_idx_band][b] = diffuseness; + + if ( hodirac_flag ) + { + if ( idx_sec == 0 ) + { + hDirAC->elevation[tmp_write_idx_band][b] = ele; + hDirAC->azimuth[tmp_write_idx_band][b] = azi; + hDirAC->energy_ratio1[tmp_write_idx_band][b] = 0.f; // not in use + } + else + { + assert( idx_sec == 1 ); + hDirAC->elevation2[tmp_write_idx_band][b] = ele; + hDirAC->azimuth2[tmp_write_idx_band][b] = azi; + hDirAC->energy_ratio2[tmp_write_idx_band][b] = 1.f - diffuseness_sec; + } + } + else + { + hDirAC->elevation[tmp_write_idx_band][b] = ele; + hDirAC->azimuth[tmp_write_idx_band][b] = azi; + } + } + tmp_write_idx_param_band = ( tmp_write_idx_param_band + 1 ) % hDirAC->dirac_md_buffer_length; + + } /* for ( block =...) */ + } /* for ( band = ...) */ + } /* for ( idx_sec = ...)*/ + + /* Bands not transmitted -> zeroed*/ + for ( b = band_grouping[band]; b < hDirAC->num_freq_bands; b++ ) + { + tmp_write_idx_band = hDirAC->dirac_bs_md_write_idx; + + for ( block = 0; block < MAX_PARAM_SPATIAL_SUBFRAMES; block++ ) + { + + hDirAC->spreadCoherence[block][b] = 0.0f; + hDirAC->surroundingCoherence[block][b] = 0.0f; + hDirAC->energy_ratio1[block][b] = 0; + + hDirAC->elevation[tmp_write_idx_band][b] = 0; + hDirAC->azimuth[tmp_write_idx_band][b] = 0; + hDirAC->diffuseness_vector[tmp_write_idx_band][b] = 0.f; + hDirAC->spreadCoherence[tmp_write_idx_band][b] = 0.0f; + hDirAC->surroundingCoherence[tmp_write_idx_band][b] = 0.0f; + hDirAC->energy_ratio1[tmp_write_idx_band][b] = 0; + tmp_write_idx_band = ( tmp_write_idx_band + 1 ) % hDirAC->dirac_md_buffer_length; + } + } + } + + /* update buffer write index */ + hDirAC->dirac_bs_md_write_idx = ( hDirAC->dirac_bs_md_write_idx + MAX_PARAM_SPATIAL_SUBFRAMES ) % hDirAC->dirac_md_buffer_length; + + return; +} + + +/*------------------------------------------------------------------------- + * ivas_dirac_dec_set_md_map() + * + * Set metadata index mapping for DirAC + *------------------------------------------------------------------------*/ + +void ivas_dirac_dec_set_md_map( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const int16_t nCldfbTs /* i : number of CLDFB time slots */ +) +{ + int16_t num_slots_in_subfr; + DIRAC_DEC_HANDLE hDirAC; + + hDirAC = st_ivas->hDirAC; +#ifdef DEBUGGING + assert( hDirAC ); +#endif + + /* adapt subframes */ + hDirAC->num_slots = nCldfbTs; + hDirAC->slots_rendered = 0; + num_slots_in_subfr = CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES; + hDirAC->subframes_rendered = 0; + + ivas_jbm_dec_get_adapted_subframes( nCldfbTs, hDirAC->subframe_nbslots, &hDirAC->nb_subframes ); + + /* set mapping according to dirac_read_idx */ + + set_s( hDirAC->render_to_md_map, 0, MAX_JBM_SUBFRAMES_5MS * JBM_CLDFB_SLOTS_IN_SUBFRAME ); + +#ifdef FIX_470_MASA_JBM_EXT + if ( st_ivas->ivas_format == MASA_FORMAT ) + { + ivas_jbm_dec_get_md_map_even_spacing( DEFAULT_JBM_CLDFB_TIMESLOTS, nCldfbTs, num_slots_in_subfr, 0, hDirAC->dirac_md_buffer_length, hDirAC->render_to_md_map ); + } + else if ( hDirAC->hConfig == NULL || hDirAC->hConfig->dec_param_estim == 0 ) +#else + if ( hDirAC->hConfig == NULL || hDirAC->hConfig->dec_param_estim == 0 ) +#endif + { + ivas_jbm_dec_get_md_map( DEFAULT_JBM_CLDFB_TIMESLOTS, nCldfbTs, num_slots_in_subfr, 0, hDirAC->dirac_md_buffer_length, hDirAC->render_to_md_map ); + } + else + { + ivas_jbm_dec_get_md_map( DEFAULT_JBM_CLDFB_TIMESLOTS, nCldfbTs, num_slots_in_subfr, hDirAC->dirac_read_idx, hDirAC->dirac_md_buffer_length, hDirAC->render_to_md_map ); + } + + if ( hDirAC->hConfig == NULL || hDirAC->hConfig->dec_param_estim == 0 ) + { + float tmp; + int16_t sf_idx, slot_idx, slot_idx_abs; + + slot_idx_abs = 0; + for ( sf_idx = 0; sf_idx < hDirAC->nb_subframes; sf_idx++ ) + { + tmp = 0.0f; + for ( slot_idx = 0; slot_idx < hDirAC->subframe_nbslots[sf_idx]; slot_idx++ ) + { + tmp += (float) hDirAC->render_to_md_map[slot_idx_abs]; + slot_idx_abs++; + } + hDirAC->render_to_md_map[sf_idx] = ( (int16_t) roundf( tmp / (float) hDirAC->subframe_nbslots[sf_idx] ) + hDirAC->dirac_read_idx ) % hDirAC->dirac_md_buffer_length; + } + + set_s( &hDirAC->render_to_md_map[hDirAC->nb_subframes], 0, MAX_JBM_SUBFRAMES_5MS * JBM_CLDFB_SLOTS_IN_SUBFRAME - hDirAC->nb_subframes ); + } + + return; +} + + +/*------------------------------------------------------------------------- + * ivas_dirac_dec() + * + * DirAC decoding process + *------------------------------------------------------------------------*/ + +void ivas_dirac_dec( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + float output_f[][L_FRAME48k], /* i/o: synthesized core-coder transport channels/DirAC output */ + const int16_t nchan_transport /* i : number of transport channels */ +) +{ + int16_t subframe_idx; + float *output_f_local[MAX_OUTPUT_CHANNELS]; + float cng_td_buffer[L_FRAME16k]; + int16_t nchan_out, n, n_samples_sf; + nchan_out = st_ivas->hIntSetup.nchan_out_woLFE + st_ivas->hIntSetup.num_lfe; + + n_samples_sf = JBM_CLDFB_SLOTS_IN_SUBFRAME * st_ivas->hDirAC->slot_size; + + for ( n = 0; n < nchan_out; n++ ) + { + output_f_local[n] = &output_f[n][0]; + } + + for ( n = 0; n < nchan_transport; n++ ) + { + st_ivas->hTcBuffer->tc[n] = output_f[n]; + } + + if ( st_ivas->nchan_transport == 1 && st_ivas->hSCE[0]->hCoreCoder[0] != NULL && st_ivas->hSCE[0]->hCoreCoder[0]->cna_dirac_flag && st_ivas->ivas_format != SBA_FORMAT ) + { + Decoder_State *st = st_ivas->hSCE[0]->hCoreCoder[0]; + st_ivas->hTcBuffer->tc[nchan_transport] = &cng_td_buffer[0]; + generate_masking_noise_lb_dirac( st->hFdCngDec->hFdCngCom, st_ivas->hTcBuffer->tc[1], DEFAULT_JBM_CLDFB_TIMESLOTS, st->cna_dirac_flag && st->flag_cna ); + } + + ivas_dirac_dec_set_md_map( st_ivas, DEFAULT_JBM_CLDFB_TIMESLOTS ); + + for ( subframe_idx = 0; subframe_idx < MAX_PARAM_SPATIAL_SUBFRAMES; subframe_idx++ ) + { + ivas_dirac_dec_render_sf( st_ivas, output_f_local, nchan_transport, NULL, NULL ); + for ( n = 0; n < nchan_out; n++ ) + { + output_f_local[n] += n_samples_sf; + } + } + + if ( st_ivas->hDirAC->hConfig->dec_param_estim == 1 ) + { + st_ivas->hDirAC->dirac_read_idx = ( st_ivas->hDirAC->dirac_read_idx + DEFAULT_JBM_CLDFB_TIMESLOTS ) % st_ivas->hDirAC->dirac_md_buffer_length; + } + else + { + st_ivas->hDirAC->dirac_read_idx = ( st_ivas->hDirAC->dirac_read_idx + DEFAULT_JBM_SUBFRAMES_5MS ) % st_ivas->hDirAC->dirac_md_buffer_length; + } + + for ( n = 0; n < nchan_transport; n++ ) + { + st_ivas->hTcBuffer->tc[n] = NULL; + } + + if ( st_ivas->nchan_transport == 1 && st_ivas->hSCE[0]->hCoreCoder[0] != NULL && st_ivas->hSCE[0]->hCoreCoder[0]->cna_dirac_flag && st_ivas->ivas_format != SBA_FORMAT ) + { + st_ivas->hTcBuffer->tc[nchan_transport] = NULL; + } + + return; +} + + +/*------------------------------------------------------------------------- + * ivas_dirac_dec_render() + * + * DirAC decoding renderer process + *------------------------------------------------------------------------*/ + +void ivas_dirac_dec_render( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ + const int16_t nchan_transport, /* i : number of transport channels */ + const uint16_t nSamplesAsked, /* i : number of CLDFB slots requested */ + uint16_t *nSamplesRendered, /* o : number of CLDFB slots rendered */ + uint16_t *nSamplesAvailable, /* o : number of CLDFB slots still to render */ + float *output_f[] /* o : rendered time signal */ +) +{ + int16_t slots_to_render, first_sf, last_sf, subframe_idx; + uint16_t slot_size, n_samples_sf, ch, nchan_intern; + DIRAC_DEC_HANDLE hDirAC; + float *output_f_local[MAX_OUTPUT_CHANNELS]; + + hDirAC = st_ivas->hDirAC; + + nchan_intern = st_ivas->hIntSetup.nchan_out_woLFE + st_ivas->hIntSetup.num_lfe; +#ifdef DEBUGGING + assert( hDirAC ); +#endif + for ( ch = 0; ch < nchan_intern; ch++ ) + { + output_f_local[ch] = output_f[ch]; + } + slot_size = NS2SA( st_ivas->hDecoderConfig->output_Fs, CLDFB_SLOT_NS ); + + /* loop for synthesis, assume we always have to render in multiples of 5ms subframes with spills */ + slots_to_render = min( hDirAC->num_slots - hDirAC->slots_rendered, nSamplesAsked / slot_size ); + *nSamplesRendered = slots_to_render * slot_size; + first_sf = hDirAC->subframes_rendered; + last_sf = first_sf; + + while ( slots_to_render > 0 ) + { + slots_to_render -= hDirAC->subframe_nbslots[last_sf]; + last_sf++; + } + +#ifdef DEBUGGING + assert( slots_to_render == 0 ); +#endif + for ( subframe_idx = first_sf; subframe_idx < last_sf; subframe_idx++ ) + { + ivas_dirac_dec_render_sf( st_ivas, output_f_local, nchan_transport, NULL, NULL ); + n_samples_sf = hDirAC->subframe_nbslots[subframe_idx] * st_ivas->hDirAC->slot_size; + for ( ch = 0; ch < nchan_intern; ch++ ) + { + output_f_local[ch] += n_samples_sf; + } + } + + if ( hDirAC->slots_rendered == hDirAC->num_slots ) + { + if ( st_ivas->hDirAC->hConfig->dec_param_estim == 1 ) + { + st_ivas->hDirAC->dirac_read_idx = ( st_ivas->hDirAC->dirac_read_idx + DEFAULT_JBM_CLDFB_TIMESLOTS ) % st_ivas->hDirAC->dirac_md_buffer_length; + } + else + { + st_ivas->hDirAC->dirac_read_idx = ( st_ivas->hDirAC->dirac_read_idx + DEFAULT_JBM_SUBFRAMES_5MS ) % st_ivas->hDirAC->dirac_md_buffer_length; + } + } + + *nSamplesAvailable = ( hDirAC->num_slots - hDirAC->slots_rendered ) * slot_size; + + return; +} + + +/*------------------------------------------------------------------------- + * ivas_dirac_dec() + * + * DirAC decoding process + *------------------------------------------------------------------------*/ + +void ivas_dirac_dec_render_sf( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + float *output_f[], /* i/o: synthesized core-coder transport channels/DirAC output */ + const int16_t nchan_transport, /* i : number of transport channels */ + float *pppQMfFrame_ts_re[IVAS_MAX_FB_MIXER_IN_CH][CLDFB_NO_COL_MAX], + float *pppQMfFrame_ts_im[IVAS_MAX_FB_MIXER_IN_CH][CLDFB_NO_COL_MAX] ) +{ + int16_t i, ch, idx_in, idx_lfe; + DIRAC_DEC_HANDLE hDirAC; + float dirEne; + float surCohEner; + float surCohRatio[CLDFB_NO_CHANNELS_MAX]; + int16_t subframe_idx; + int16_t slot_idx, index_slot; + int16_t hodirac_flag; + float *p_Rmat; + int16_t slot_idx_start, slot_idx_start_cldfb_synth, md_idx; + + /*CLDFB: last output channels reserved to LFT for CICPx*/ + float Cldfb_RealBuffer[MAX_OUTPUT_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; + float Cldfb_ImagBuffer[MAX_OUTPUT_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; +#ifdef SPLIT_REND_WITH_HEAD_ROT + float Cldfb_RealBuffer_Binaural[MAX_HEAD_ROT_POSES][BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; + float Cldfb_ImagBuffer_Binaural[MAX_HEAD_ROT_POSES][BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; +#else + float Cldfb_RealBuffer_Binaural[BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; + float Cldfb_ImagBuffer_Binaural[BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; +#endif +#ifdef MASA_AND_OBJECTS + float Cldfb_RealBuffer_Temp[2][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; /* Todo Nokia: Temporary, to be removed once function calls have been refactored to accept another size */ + float Cldfb_ImagBuffer_Temp[2][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; /* Todo Nokia: Temporary, to be removed once function calls have been refactored to accept another size */ +#endif + int16_t index, num_freq_bands; + + /* local copies of azi, ele, diffuseness */ + int16_t azimuth[CLDFB_NO_CHANNELS_MAX]; + int16_t elevation[CLDFB_NO_CHANNELS_MAX]; + float diffuseness_vector[CLDFB_NO_CHANNELS_MAX]; + + DIRAC_DEC_STACK_MEM DirAC_mem; + float *reference_power, *reference_power_smooth; + float *onset_filter, *onset_filter_subframe, *p_onset_filter = NULL; + uint16_t coherence_flag; + + push_wmops( "ivas_dirac_dec_render" ); + + /* Initialize aux buffers */ + hDirAC = st_ivas->hDirAC; + + DirAC_mem = st_ivas->hDirAC->stack_mem; + + reference_power = DirAC_mem.reference_power; + reference_power_smooth = DirAC_mem.reference_power + hDirAC->num_freq_bands; + onset_filter = DirAC_mem.onset_filter; +#ifdef FIX_614_ADD_TO_NULL_PTR_DIRAC_SETUP + onset_filter_subframe = ( DirAC_mem.onset_filter == NULL ) ? NULL : DirAC_mem.onset_filter + hDirAC->num_freq_bands; +#else + onset_filter_subframe = DirAC_mem.onset_filter + hDirAC->num_freq_bands; +#endif + + hodirac_flag = ivas_get_hodirac_flag( st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->sba_analysis_order ); + + if ( st_ivas->hQMetaData != NULL && st_ivas->ivas_format != SBA_FORMAT ) + { + coherence_flag = st_ivas->hQMetaData->coherence_flag; + } + else + { + coherence_flag = 0; + } + +#ifdef DEBUG_MODE_DIRAC + { + int16_t n, tmp[IVAS_SPAR_MAX_CH * L_FRAME48k]; + char file_name[50] = { 0 }; + const int16_t output_frame = st_ivas->hDecoderConfig->output_Fs / FRAMES_PER_SEC; + + for ( n = 0; n < nchan_transport; n++ ) + { + for ( i = 0; i < output_frame; i++ ) + { + tmp[nchan_transport * i + n] = (int16_t) ( output_f[n][i] + 0.5f ); + } + } + sprintf( file_name, "./res/ivas_dirac_dec_DMX%d.%d.pcm", nchan_transport, (int16_t) ( output_frame * 0.05 ) ); + dbgwrite( tmp, sizeof( int16_t ), nchan_transport * output_frame, 1, file_name ); + } +#endif + + /* Subframe loop */ + slot_idx_start = hDirAC->slots_rendered; + slot_idx_start_cldfb_synth = 0; + + subframe_idx = hDirAC->subframes_rendered; + if ( hDirAC->hConfig->dec_param_estim == FALSE ) + { + md_idx = hDirAC->render_to_md_map[subframe_idx]; + } + else + { + md_idx = hDirAC->render_to_md_map[slot_idx_start]; + } + /* ToDo: Another workaround for self test BE */ + + /* copy parameters into local buffers*/ + if ( hDirAC->hConfig->dec_param_estim == FALSE ) + { + mvs2s( hDirAC->azimuth[hDirAC->render_to_md_map[subframe_idx]], azimuth, hDirAC->num_freq_bands ); + mvs2s( hDirAC->elevation[hDirAC->render_to_md_map[subframe_idx]], elevation, hDirAC->num_freq_bands ); + mvr2r( hDirAC->diffuseness_vector[hDirAC->render_to_md_map[subframe_idx]], diffuseness_vector, hDirAC->num_freq_bands ); + } + else + { + set_zero( diffuseness_vector, hDirAC->num_freq_bands ); + } + + if ( hDirAC->synthesisConf != DIRAC_SYNTHESIS_GAIN_SHD ) + { + set_zero( reference_power_smooth, hDirAC->num_freq_bands ); + } + else + { + set_zero( onset_filter_subframe, hDirAC->num_freq_bands ); + } + + if ( st_ivas->hCombinedOrientationData && st_ivas->hCombinedOrientationData->enableCombinedOrientation[subframe_idx] ) + { + p_Rmat = &st_ivas->hCombinedOrientationData->Rmat[subframe_idx][0][0]; + + if ( st_ivas->hCombinedOrientationData->shd_rot_max_order == 0 ) + { + num_freq_bands = hDirAC->band_grouping[hDirAC->hConfig->enc_param_start_band]; + if ( hDirAC->hConfig->dec_param_estim == FALSE ) + { + rotateAziEle_DirAC( azimuth, elevation, num_freq_bands, hDirAC->num_freq_bands, p_Rmat ); + } + } + } + else + { + p_Rmat = 0; + } + + if ( hDirAC->hConfig->dec_param_estim == FALSE ) + { + /* compute response */ + if ( hDirAC->synthesisConf != DIRAC_SYNTHESIS_GAIN_SHD ) + { + ivas_dirac_dec_compute_power_factors( hDirAC->num_freq_bands, + diffuseness_vector, + hDirAC->h_output_synthesis_psd_params.max_band_decorr, + hDirAC->h_output_synthesis_psd_state.direct_power_factor, + hDirAC->h_output_synthesis_psd_state.diffuse_power_factor ); + + if ( coherence_flag ) + { + for ( i = 0; i < hDirAC->num_freq_bands; i++ ) + { + dirEne = hDirAC->h_output_synthesis_psd_state.direct_power_factor[i]; + surCohEner = hDirAC->h_output_synthesis_psd_state.diffuse_power_factor[i] * hDirAC->surroundingCoherence[md_idx][i]; + hDirAC->h_output_synthesis_psd_state.diffuse_power_factor[i] -= surCohEner; + hDirAC->h_output_synthesis_psd_state.direct_power_factor[i] += surCohEner; + + surCohRatio[i] = surCohEner / ( 1e-12f + dirEne + surCohEner ); + } + } + else + { + set_zero( surCohRatio, hDirAC->num_freq_bands ); + } + } + else + { + ivas_dirac_dec_compute_gain_factors( hDirAC->num_freq_bands, + hDirAC->diffuseness_vector[md_idx], + hDirAC->h_output_synthesis_psd_params.max_band_decorr, + hDirAC->h_output_synthesis_psd_state.direct_power_factor, + hDirAC->h_output_synthesis_psd_state.diffuse_power_factor ); + + if ( coherence_flag ) + { + for ( i = 0; i < hDirAC->num_freq_bands; i++ ) + { + surCohRatio[i] = hDirAC->surroundingCoherence[md_idx][i]; + } + } + else + { + set_zero( surCohRatio, hDirAC->num_freq_bands ); + } + } + if ( st_ivas->hCombinedOrientationData && st_ivas->hCombinedOrientationData->enableCombinedOrientation[subframe_idx] && st_ivas->hCombinedOrientationData->shd_rot_max_order == 1 ) + { + ivas_dirac_dec_compute_directional_responses( hDirAC, + st_ivas->hVBAPdata, + st_ivas->hMasa, +#ifdef MASA_AND_OBJECTS + st_ivas->hMasaIsmData, +#endif + azimuth, + elevation, + md_idx, + surCohRatio, + st_ivas->hCombinedOrientationData->shd_rot_max_order, + p_Rmat, + hodirac_flag ); + } + else + { + ivas_dirac_dec_compute_directional_responses( hDirAC, + st_ivas->hVBAPdata, + st_ivas->hMasa, +#ifdef MASA_AND_OBJECTS + st_ivas->hMasaIsmData, +#endif + azimuth, + elevation, + md_idx, + surCohRatio, + 0, + NULL, + hodirac_flag ); + } + } + +#ifdef MASA_AND_OBJECTS + // Todo OMASA JBM: This might need adjustments + if ( st_ivas->ivas_format == MASA_ISM_FORMAT && nchan_transport == 2 ) + { + for ( slot_idx = 0; slot_idx < hDirAC->subframe_nbslots[subframe_idx]; slot_idx++ ) + { + index_slot = slot_idx_start + slot_idx; + + /* CLDFB Analysis*/ + for ( ch = 0; ch < nchan_transport; ch++ ) + { + cldfbAnalysis_ts( &( st_ivas->hTcBuffer->tc[hDirAC->sba_map_tc[ch]][hDirAC->num_freq_bands * index_slot] ), + Cldfb_RealBuffer_Temp[ch][slot_idx], + Cldfb_ImagBuffer_Temp[ch][slot_idx], + hDirAC->num_freq_bands, + st_ivas->cldfbAnaDec[ch] ); + } + } + + if ( st_ivas->ism_mode != ISM_MASA_MODE_DISC && st_ivas->ism_mode != ISM_MASA_MODE_MASA_ONE_OBJ ) + { + preProcessStereoTransportsForMovedObjects( st_ivas, Cldfb_RealBuffer_Temp, Cldfb_ImagBuffer_Temp, hDirAC->num_freq_bands, subframe_idx ); + } + } +#endif + + for ( slot_idx = 0; slot_idx < hDirAC->subframe_nbslots[subframe_idx]; slot_idx++ ) + { + index_slot = slot_idx_start + slot_idx; + if ( hDirAC->hConfig->dec_param_estim == TRUE ) + { + md_idx = hDirAC->render_to_md_map[index_slot]; + } + else + { + md_idx = hDirAC->render_to_md_map[subframe_idx]; + } + + if ( st_ivas->ivas_format == SBA_FORMAT ) + { + for ( ch = 0; ch < nchan_transport; ch++ ) + { + mvr2r( pppQMfFrame_ts_re[ch][slot_idx], Cldfb_RealBuffer[ch][0], hDirAC->num_freq_bands ); + mvr2r( pppQMfFrame_ts_im[ch][slot_idx], Cldfb_ImagBuffer[ch][0], hDirAC->num_freq_bands ); + } + } +#ifdef MASA_AND_OBJECTS + // Todo OMASA JBM: This might need adjustments + else if ( st_ivas->ivas_format == MASA_ISM_FORMAT && nchan_transport == 2 ) + { + for ( ch = 0; ch < nchan_transport; ch++ ) + { + mvr2r( Cldfb_RealBuffer_Temp[ch][slot_idx], Cldfb_RealBuffer[ch][0], hDirAC->num_freq_bands ); + mvr2r( Cldfb_ImagBuffer_Temp[ch][slot_idx], Cldfb_ImagBuffer[ch][0], hDirAC->num_freq_bands ); + } + } +#endif + else + { + /* CLDFB Analysis*/ + for ( ch = 0; ch < nchan_transport; ch++ ) + { + cldfbAnalysis_ts( &( st_ivas->hTcBuffer->tc[hDirAC->sba_map_tc[ch]][hDirAC->num_freq_bands * index_slot] ), + Cldfb_RealBuffer[ch][0], + Cldfb_ImagBuffer[ch][0], + hDirAC->num_freq_bands, + st_ivas->cldfbAnaDec[ch] ); + } + } + + /* CNG in DirAC, extra CLDFB ana for CNA*/ + if ( st_ivas->nchan_transport == 1 && st_ivas->hSCE[0]->hCoreCoder[0] != NULL && st_ivas->hSCE[0]->hCoreCoder[0]->cna_dirac_flag && st_ivas->ivas_format != SBA_FORMAT ) + { + Decoder_State *st = st_ivas->hSCE[0]->hCoreCoder[0]; + + generate_masking_noise_dirac( st->hFdCngDec->hFdCngCom, + st_ivas->cldfbAnaDec[1], + st_ivas->hTcBuffer->tc[1], + Cldfb_RealBuffer[1][0], + Cldfb_ImagBuffer[1][0], + index_slot, + st->cna_dirac_flag && st->flag_cna, + ( st->core_brate == FRAME_NO_DATA || st->core_brate == SID_2k40 ) && st->cng_type == FD_CNG && st->cng_sba_flag ); + } + + /* LFE synthesis */ + if ( st_ivas->mc_mode == MC_MODE_MCMASA && !hDirAC->hOutSetup.separateChannelEnabled && !( hDirAC->hOutSetup.output_config == AUDIO_CONFIG_LS_CUSTOM && hDirAC->hOutSetup.num_lfe == 0 ) ) + { + ivas_lfe_synth_with_cldfb( st_ivas->hMasa->hMasaLfeSynth, + Cldfb_RealBuffer, Cldfb_ImagBuffer, + Cldfb_RealBuffer[MAX_OUTPUT_CHANNELS - 1], Cldfb_ImagBuffer[MAX_OUTPUT_CHANNELS - 1], + slot_idx, + md_idx, + nchan_transport ); + } + + /*-----------------------------------------------------------------* + * protoype signal computation + *-----------------------------------------------------------------*/ + + if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) + { + if ( st_ivas->hCombinedOrientationData && st_ivas->hCombinedOrientationData->enableCombinedOrientation[subframe_idx] && st_ivas->hCombinedOrientationData->shd_rot_max_order == 0 ) + { + protoSignalComputation_shd( Cldfb_RealBuffer, Cldfb_ImagBuffer, + hDirAC->h_output_synthesis_psd_state.proto_direct_buffer_f, + hDirAC->h_output_synthesis_psd_state.proto_diffuse_buffer_f, + reference_power, slot_idx, nchan_transport, + hDirAC->num_outputs_diff, + hDirAC->num_freq_bands, + p_Rmat ); + } + else + { + protoSignalComputation_shd( Cldfb_RealBuffer, Cldfb_ImagBuffer, + hDirAC->h_output_synthesis_psd_state.proto_direct_buffer_f, + hDirAC->h_output_synthesis_psd_state.proto_diffuse_buffer_f, + reference_power, slot_idx, nchan_transport, + hDirAC->num_outputs_diff, + hDirAC->num_freq_bands, + 0 ); + } + } + else if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_MONO ) + { + protoSignalComputation2( Cldfb_RealBuffer, Cldfb_ImagBuffer, hDirAC->proto_frame_f, + hDirAC->h_output_synthesis_psd_state.proto_direct_buffer_f, + reference_power, hDirAC->h_output_synthesis_psd_state.proto_power_smooth, + 0, slot_idx, hDirAC->num_freq_bands, hDirAC->masa_stereo_type_detect ); + } + else + { + switch ( nchan_transport ) + { + case 11: + case 8: + case 6: + case 4: + protoSignalComputation4( Cldfb_RealBuffer, Cldfb_ImagBuffer, + hDirAC->proto_frame_f, + hDirAC->h_output_synthesis_psd_state.proto_direct_buffer_f, + reference_power, + hDirAC->h_output_synthesis_psd_state.proto_power_smooth, + slot_idx, hDirAC->num_outputs_diff, + hDirAC->num_freq_bands, + hDirAC->hoa_decoder, + nchan_transport, + hDirAC->sba_map_tc ); + break; + case 2: + protoSignalComputation2( Cldfb_RealBuffer, Cldfb_ImagBuffer, + hDirAC->proto_frame_f, + hDirAC->h_output_synthesis_psd_state.proto_direct_buffer_f, + reference_power, + hDirAC->h_output_synthesis_psd_state.proto_power_smooth, + hDirAC->hOutSetup.is_loudspeaker_setup, + slot_idx, + hDirAC->num_freq_bands, + hDirAC->masa_stereo_type_detect ); + break; + case 1: + protoSignalComputation1( Cldfb_RealBuffer, Cldfb_ImagBuffer, + hDirAC->proto_frame_f, + hDirAC->h_output_synthesis_psd_state.proto_direct_buffer_f, + reference_power, + hDirAC->h_output_synthesis_psd_state.proto_power_smooth, + slot_idx, + hDirAC->num_protos_diff, + hDirAC->num_freq_bands ); + break; + default: + return; + } + } + + + /*-----------------------------------------------------------------* + * Compute DirAC parameters at decoder side + *-----------------------------------------------------------------*/ + + if ( hDirAC->hConfig->dec_param_estim == TRUE ) + { + mvs2s( &hDirAC->azimuth[md_idx][hDirAC->hConfig->enc_param_start_band], &azimuth[hDirAC->hConfig->enc_param_start_band], hDirAC->num_freq_bands - hDirAC->hConfig->enc_param_start_band ); + mvs2s( &hDirAC->elevation[md_idx][hDirAC->hConfig->enc_param_start_band], &elevation[hDirAC->hConfig->enc_param_start_band], hDirAC->num_freq_bands - hDirAC->hConfig->enc_param_start_band ); + if ( ( st_ivas->hDecoderConfig->Opt_Headrotation || st_ivas->hDecoderConfig->Opt_ExternalOrientation ) && st_ivas->hCombinedOrientationData->shd_rot_max_order == 0 ) + { + num_freq_bands = hDirAC->band_grouping[hDirAC->hConfig->enc_param_start_band]; + rotateAziEle_DirAC( azimuth, elevation, num_freq_bands, hDirAC->num_freq_bands, p_Rmat ); + } + + hDirAC->index_buffer_intensity = ( hDirAC->index_buffer_intensity % DIRAC_NO_COL_AVG_DIFF ) + 1; /* averaging_length = 32 */ + + index = hDirAC->index_buffer_intensity; + + num_freq_bands = hDirAC->band_grouping[hDirAC->hConfig->enc_param_start_band]; + + computeIntensityVector_dec( Cldfb_RealBuffer, + Cldfb_ImagBuffer, + num_freq_bands, + hDirAC->buffer_intensity_real[0][index - 1], + hDirAC->buffer_intensity_real[1][index - 1], + hDirAC->buffer_intensity_real[2][index - 1] ); + + computeDirectionAngles( hDirAC->buffer_intensity_real[0][index - 1], + hDirAC->buffer_intensity_real[1][index - 1], + hDirAC->buffer_intensity_real[2][index - 1], + num_freq_bands, + azimuth, + elevation ); + + mvr2r( reference_power, &( hDirAC->buffer_energy[( index - 1 ) * num_freq_bands] ), num_freq_bands ); + + computeDiffuseness( hDirAC->buffer_intensity_real, hDirAC->buffer_energy, num_freq_bands, hDirAC->diffuseness_vector[md_idx] ); + } + +#ifdef DEBUG_MODE_DIRAC + { + static FILE *fp_direction_vector = NULL, *fp_diffuseness = NULL, *fp_referencePower = NULL; + + + if ( fp_direction_vector == NULL ) + fp_direction_vector = fopen( "./res/dbg_direction_vector_C_dec.bin", "wb" ); + if ( fp_diffuseness == NULL ) + fp_diffuseness = fopen( "./res/dbg_diffuseness_C_dec.bin", "wb" ); + if ( fp_referencePower == NULL ) + fp_referencePower = fopen( "./res/dbg_reference_power_C_dec.bin", "wb" ); + + + for ( i = 0; i < hDirAC->num_freq_bands; i++ ) + { + float radius_length; + float dv[3]; + + if ( hDirAC->hConfig->dec_param_estim == FALSE ) + { + radius_length = cos( hDirAC->elevation[subframe_idx][i] * PI_OVER_180 ); + dv[0] = radius_length * cos( hDirAC->azimuth[subframe_idx][i] * PI_OVER_180 ); + dv[1] = radius_length * sin( hDirAC->azimuth[subframe_idx][i] * PI_OVER_180 ); + dv[2] = sin( hDirAC->elevation[subframe_idx][i] * PI_OVER_180 ); + + fwrite( dv, sizeof( float ), 3, fp_direction_vector ); + fwrite( &( hDirAC->diffuseness_vector[0][i] ), sizeof( float ), 1, fp_diffuseness ); + if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) + { + reference_power[i] = Cldfb_RealBuffer[0][0][i] * Cldfb_RealBuffer[0][0][i] + Cldfb_ImagBuffer[0][0][i] * Cldfb_ImagBuffer[0][0][i]; + } + fwrite( &( reference_power[i] ), sizeof( float ), 1, fp_referencePower ); + } + else + { + radius_length = cos( hDirAC->elevation[index_slot][i] * PI_OVER_180 ); + dv[0] = radius_length * cos( hDirAC->azimuth[index_slot][i] * PI_OVER_180 ); + dv[1] = radius_length * sin( hDirAC->azimuth[index_slot][i] * PI_OVER_180 ); + dv[2] = sin( hDirAC->elevation[index_slot][i] * PI_OVER_180 ); + + fwrite( dv, sizeof( float ), 3, fp_direction_vector ); + fwrite( &( hDirAC->diffuseness_vector[index_slot][i] ), sizeof( float ), 1, fp_diffuseness ); + fwrite( &( reference_power[i] ), sizeof( float ), 1, fp_referencePower ); + } + } + } +#endif + + /*-----------------------------------------------------------------* + * frequency domain decorrelation + *-----------------------------------------------------------------*/ + + if ( hDirAC->proto_signal_decorr_on == 1 ) + { + /* decorrelate prototype frame */ + if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) + { + ivas_dirac_dec_decorr_process( hDirAC->num_freq_bands, + hDirAC->num_outputs_diff, + hDirAC->num_protos_diff, + hDirAC->synthesisConf, + nchan_transport, + hDirAC->h_output_synthesis_psd_state.proto_diffuse_buffer_f + slot_idx * 2 * hDirAC->num_freq_bands * hDirAC->num_outputs_diff, + hDirAC->num_protos_diff, + hDirAC->proto_index_diff, + hDirAC->h_output_synthesis_psd_state.proto_diffuse_buffer_f + slot_idx * 2 * hDirAC->num_freq_bands * hDirAC->num_outputs_diff + 2 * hDirAC->num_freq_bands * min( 4, nchan_transport ), + onset_filter, + hDirAC->h_freq_domain_decorr_ap_params, + hDirAC->h_freq_domain_decorr_ap_state ); + + v_multc( onset_filter, 0.25f, onset_filter, hDirAC->num_freq_bands ); + v_add( onset_filter, onset_filter_subframe, onset_filter_subframe, hDirAC->num_freq_bands ); + p_onset_filter = onset_filter_subframe; + } + else + { + ivas_dirac_dec_decorr_process( hDirAC->num_freq_bands, + hDirAC->num_outputs_diff, + hDirAC->num_protos_diff, + hDirAC->synthesisConf, + nchan_transport, + hDirAC->proto_frame_f, + hDirAC->num_protos_diff, + hDirAC->proto_index_diff, + DirAC_mem.frame_dec_f, + onset_filter, + hDirAC->h_freq_domain_decorr_ap_params, + hDirAC->h_freq_domain_decorr_ap_state ); + + hDirAC->proto_frame_dec_f = DirAC_mem.frame_dec_f; + p_onset_filter = onset_filter; + } + } + else + { + if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) + { + set_f( onset_filter_subframe, 1.f, hDirAC->num_freq_bands ); + p_onset_filter = onset_filter_subframe; + } + else + { + /* no frequency domain decorrelation: use prototype frame */ + hDirAC->proto_frame_dec_f = hDirAC->proto_frame_f; + p_onset_filter = NULL; + } + } + + /*-----------------------------------------------------------------* + * output synthesis + *-----------------------------------------------------------------*/ + + if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_PSD_LS || hDirAC->synthesisConf == DIRAC_SYNTHESIS_PSD_SHD ) + { + /*Compute diffuse prototypes*/ + ivas_dirac_dec_compute_diffuse_proto( hDirAC, slot_idx ); + } + + /*Compute PSDs*/ + if ( st_ivas->hCombinedOrientationData && st_ivas->hCombinedOrientationData->enableCombinedOrientation[subframe_idx] && st_ivas->hCombinedOrientationData->shd_rot_max_order > 0 ) + { + ivas_dirac_dec_output_synthesis_process_slot( reference_power, + p_onset_filter, + azimuth, + elevation, + hDirAC->diffuseness_vector[md_idx], + hDirAC, + st_ivas->hCombinedOrientationData->shd_rot_max_order, + p_Rmat, + st_ivas->hVBAPdata, + hDirAC->hOutSetup, + nchan_transport, + md_idx, + hodirac_flag ); + } + else + { + ivas_dirac_dec_output_synthesis_process_slot( reference_power, + p_onset_filter, + azimuth, + elevation, + hDirAC->diffuseness_vector[md_idx], + hDirAC, + 0, + 0, + st_ivas->hVBAPdata, + hDirAC->hOutSetup, + nchan_transport, + md_idx, + hodirac_flag ); + } + + if ( hDirAC->hConfig->dec_param_estim ) + { + float fac = 1.0f / (float) hDirAC->subframe_nbslots[subframe_idx]; + v_multc_acc( hDirAC->diffuseness_vector[md_idx], fac, diffuseness_vector, hDirAC->num_freq_bands ); + } + + if ( hDirAC->synthesisConf != DIRAC_SYNTHESIS_GAIN_SHD ) + { + v_add( reference_power, reference_power_smooth, reference_power_smooth, hDirAC->num_freq_bands ); + } + } + + ivas_dirac_dec_output_synthesis_get_interpolator( &hDirAC->h_output_synthesis_psd_params, hDirAC->subframe_nbslots[subframe_idx] ); + + + if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) + { + ivas_dirac_dec_output_synthesis_process_subframe_gain_shd( Cldfb_RealBuffer, + Cldfb_ImagBuffer, + hDirAC, + nchan_transport, + hDirAC->subframe_nbslots[subframe_idx], + p_onset_filter, + diffuseness_vector, + hodirac_flag ); + } + else + { + /* Determine encoding quality based additional smoothing factor */ + float qualityBasedSmFactor = 1.0f; + + if ( st_ivas->hMasa != NULL ) + { + qualityBasedSmFactor = st_ivas->hMasa->data.dir_decode_quality; + qualityBasedSmFactor *= qualityBasedSmFactor; + } + + + ivas_dirac_dec_output_synthesis_process_subframe_psd_ls( Cldfb_RealBuffer, + Cldfb_ImagBuffer, + hDirAC, + hDirAC->subframe_nbslots[subframe_idx], + diffuseness_vector, + reference_power_smooth, + qualityBasedSmFactor ); + } + + /*-----------------------------------------------------------------* + * CLDFB synthesis (and binaural rendering) + *-----------------------------------------------------------------*/ + + index_slot = slot_idx_start_cldfb_synth; + + if ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) + { + /* Perform binaural rendering */ + ivas_binRenderer( st_ivas->hBinRenderer, +#ifdef SPLIT_REND_WITH_HEAD_ROT + &st_ivas->splitBinRend.splitrend.multiBinPoseData, +#endif + st_ivas->hCombinedOrientationData, + subframe_idx, + hDirAC->subframe_nbslots[subframe_idx], + Cldfb_RealBuffer_Binaural, + Cldfb_ImagBuffer_Binaural, + Cldfb_RealBuffer, + Cldfb_ImagBuffer ); - if ( hodirac_flag ) - { - if ( idx_sec == 0 ) - { - hSpatParamRendCom->elevation[tmp_write_idx_band][b] = ele; - hSpatParamRendCom->azimuth[tmp_write_idx_band][b] = azi; - hSpatParamRendCom->energy_ratio1[tmp_write_idx_band][b] = 0.f; // not in use - } - else - { - assert( idx_sec == 1 ); - hSpatParamRendCom->elevation2[tmp_write_idx_band][b] = ele; - hSpatParamRendCom->azimuth2[tmp_write_idx_band][b] = azi; - hSpatParamRendCom->energy_ratio2[tmp_write_idx_band][b] = 1.f - diffuseness_sec; - } - } - else - { - hSpatParamRendCom->elevation[tmp_write_idx_band][b] = ele; - hSpatParamRendCom->azimuth[tmp_write_idx_band][b] = azi; - } +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( ( st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || + ( st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) + { + int16_t pos_idx; +#ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG + for ( pos_idx = 0; pos_idx < st_ivas->hBinRenderer->numPoses; pos_idx++ ) +#else + for ( pos_idx = 0; pos_idx < st_ivas->hBinRenderer->numPoses; pos_idx++ ) +#endif + { + for ( slot_idx = 0; slot_idx < hDirAC->subframe_nbslots[subframe_idx]; slot_idx++ ) + { + for ( ch = 0; ch < st_ivas->hDecoderConfig->nchan_out; ch++ ) + { + mvr2r( Cldfb_RealBuffer_Binaural[pos_idx][ch][slot_idx], st_ivas->splitBinRend.hMultiBinCldfbData->Cldfb_RealBuffer_Binaural[( pos_idx * BINAURAL_CHANNELS ) + ch][slot_idx_start + slot_idx], hDirAC->num_freq_bands ); + mvr2r( Cldfb_ImagBuffer_Binaural[pos_idx][ch][slot_idx], st_ivas->splitBinRend.hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural[( pos_idx * BINAURAL_CHANNELS ) + ch][slot_idx_start + slot_idx], hDirAC->num_freq_bands ); } - tmp_write_idx_param_band = ( tmp_write_idx_param_band + 1 ) % hSpatParamRendCom->dirac_md_buffer_length; + } + } + } +#endif + /* Inverse CLDFB*/ + for ( ch = 0; ch < st_ivas->hDecoderConfig->nchan_out; ch++ ) + { + /* open CLDFB buffer up to CLDFB_NO_CHANNELS_MAX bands for 48kHz */ + float *RealBuffer[MAX_PARAM_SPATIAL_SUBFRAMES]; + float *ImagBuffer[MAX_PARAM_SPATIAL_SUBFRAMES]; - } /* for ( block =...) */ - } /* for ( band = ...) */ - } /* for ( idx_sec = ...)*/ + for ( i = 0; i < hDirAC->subframe_nbslots[subframe_idx]; i++ ) + { +#ifdef SPLIT_REND_WITH_HEAD_ROT + RealBuffer[i] = Cldfb_RealBuffer_Binaural[0][ch][i]; + ImagBuffer[i] = Cldfb_ImagBuffer_Binaural[0][ch][i]; +#else + RealBuffer[i] = Cldfb_RealBuffer_Binaural[ch][i]; + ImagBuffer[i] = Cldfb_ImagBuffer_Binaural[ch][i]; +#endif + } - /* Bands not transmitted -> zeroed*/ - for ( b = band_grouping[band]; b < hSpatParamRendCom->num_freq_bands; b++ ) + cldfbSynthesis( RealBuffer, + ImagBuffer, + &( output_f[ch][index_slot * hDirAC->num_freq_bands] ), + hDirAC->num_freq_bands * hDirAC->subframe_nbslots[subframe_idx], + st_ivas->cldfbSynDec[ch] ); + } + } + else if ( st_ivas->ivas_format == SBA_FORMAT ) + { + for ( ch = 0; ch < hDirAC->hOutSetup.nchan_out_woLFE; ch++ ) + { + for ( slot_idx = 0; slot_idx < hDirAC->subframe_nbslots[subframe_idx]; slot_idx++ ) + { + mvr2r( Cldfb_RealBuffer[ch][slot_idx], pppQMfFrame_ts_re[ch][slot_idx], hDirAC->num_freq_bands ); + mvr2r( Cldfb_ImagBuffer[ch][slot_idx], pppQMfFrame_ts_im[ch][slot_idx], hDirAC->num_freq_bands ); + } + } + } + else + { + float *RealBuffer[MAX_PARAM_SPATIAL_SUBFRAMES]; + float *ImagBuffer[MAX_PARAM_SPATIAL_SUBFRAMES]; + int16_t outchannels; + + idx_in = 0; + idx_lfe = 0; + + outchannels = hDirAC->hOutSetup.nchan_out_woLFE + hDirAC->hOutSetup.num_lfe; + if ( hDirAC->hOutSetup.separateChannelEnabled && ( hDirAC->hOutSetup.output_config == AUDIO_CONFIG_5_1 || + hDirAC->hOutSetup.output_config == AUDIO_CONFIG_7_1 || + hDirAC->hOutSetup.output_config == AUDIO_CONFIG_5_1_2 || + hDirAC->hOutSetup.output_config == AUDIO_CONFIG_5_1_4 || + hDirAC->hOutSetup.output_config == AUDIO_CONFIG_7_1_4 || + ( hDirAC->hOutSetup.output_config == AUDIO_CONFIG_LS_CUSTOM && st_ivas->hLsSetupCustom->separate_ch_found ) ) ) { - tmp_write_idx_band = hSpatParamRendCom->dirac_bs_md_write_idx; + outchannels++; + } - for ( block = 0; block < MAX_PARAM_SPATIAL_SUBFRAMES; block++ ) + if ( hDirAC->hOutSetup.separateChannelEnabled && hDirAC->hOutSetup.output_config == AUDIO_CONFIG_LS_CUSTOM ) + { + float tmp_separated[L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES]; + float tmp_lfe[L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES]; + const int16_t subframe_start_sample = index_slot * hDirAC->num_freq_bands; + const int16_t num_samples_subframe = hDirAC->num_freq_bands * hDirAC->subframe_nbslots[subframe_idx]; + + /* Move the separated and the LFE channels to temporary variables as spatial synthesis may overwrite current channels */ + mvr2r( &( output_f[st_ivas->hOutSetup.separateChannelIndex][subframe_start_sample] ), tmp_separated, num_samples_subframe ); + mvr2r( &( output_f[LFE_CHANNEL][subframe_start_sample] ), tmp_lfe, num_samples_subframe ); + + for ( ch = 0; ch < outchannels; ch++ ) { + if ( ( hDirAC->hOutSetup.num_lfe > 0 ) && ( hDirAC->hOutSetup.index_lfe[idx_lfe] == ch ) ) + { + /* Move the LFE channel to the correct place */ + mvr2r( tmp_lfe, &( output_f[ch][subframe_start_sample] ), num_samples_subframe ); + + if ( idx_lfe < ( hDirAC->hOutSetup.num_lfe - 1 ) ) + { + idx_lfe++; + } + } + else if ( ( st_ivas->hLsSetupCustom->separate_ch_found ) && ( hDirAC->hOutSetup.separateChannelIndex == ch ) ) + { + /* Move the separated channel to the correct place. Thus, the separated channel is + * combined with the synthesized channels here when there is a matching channel. */ + mvr2r( tmp_separated, &( output_f[ch][subframe_start_sample] ), num_samples_subframe ); + } + else + { + /* open CLDFB buffer up to CLDFB_NO_CHANNELS_MAX bands for 48kHz */ + for ( i = 0; i < hDirAC->subframe_nbslots[subframe_idx]; i++ ) + { + RealBuffer[i] = Cldfb_RealBuffer[idx_in][i]; + ImagBuffer[i] = Cldfb_ImagBuffer[idx_in][i]; + } + cldfbSynthesis( RealBuffer, ImagBuffer, &( output_f[ch][subframe_start_sample] ), num_samples_subframe, st_ivas->cldfbSynDec[idx_in] ); + + if ( !st_ivas->hLsSetupCustom->separate_ch_found ) + { + /* Pan the separated channel and mix with the synthesized channels. Thus, the separated channel + * is combined with the synthesized channels here when there is no matching channel. */ + v_multc_acc( tmp_separated, st_ivas->hLsSetupCustom->separate_ch_gains[idx_in], &( output_f[ch][subframe_start_sample] ), num_samples_subframe ); + } - hSpatParamRendCom->spreadCoherence[block][b] = 0.0f; - hSpatParamRendCom->surroundingCoherence[block][b] = 0.0f; - hSpatParamRendCom->energy_ratio1[block][b] = 0; + idx_in++; + } + } + } + else + { + for ( ch = 0; ch < outchannels; ch++ ) + { + if ( ( hDirAC->hOutSetup.num_lfe > 0 ) && ( hDirAC->hOutSetup.index_lfe[idx_lfe] == ch ) ) + { + if ( st_ivas->mc_mode == MC_MODE_MCMASA && !hDirAC->hOutSetup.separateChannelEnabled ) + { + for ( i = 0; i < hDirAC->subframe_nbslots[subframe_idx]; i++ ) + { + RealBuffer[i] = Cldfb_RealBuffer[MAX_OUTPUT_CHANNELS - 1][i]; + ImagBuffer[i] = Cldfb_ImagBuffer[MAX_OUTPUT_CHANNELS - 1][i]; + } + cldfbSynthesis( RealBuffer, ImagBuffer, &( output_f[ch][index_slot * hDirAC->num_freq_bands] ), hDirAC->num_freq_bands * hDirAC->subframe_nbslots[subframe_idx], st_ivas->cldfbSynDec[hDirAC->hOutSetup.nchan_out_woLFE + idx_lfe] ); + } + else if ( st_ivas->mc_mode == MC_MODE_MCMASA && hDirAC->hOutSetup.separateChannelEnabled ) + { + /* LFE has been synthesized in the time domain, do nothing. */ + } + else + { + set_zero( &( output_f[ch][index_slot * hDirAC->num_freq_bands] ), hDirAC->subframe_nbslots[subframe_idx] * hDirAC->num_freq_bands ); + } - hSpatParamRendCom->elevation[tmp_write_idx_band][b] = 0; - hSpatParamRendCom->azimuth[tmp_write_idx_band][b] = 0; - hSpatParamRendCom->diffuseness_vector[tmp_write_idx_band][b] = 0.f; - hSpatParamRendCom->spreadCoherence[tmp_write_idx_band][b] = 0.0f; - hSpatParamRendCom->surroundingCoherence[tmp_write_idx_band][b] = 0.0f; - hSpatParamRendCom->energy_ratio1[tmp_write_idx_band][b] = 0; - tmp_write_idx_band = ( tmp_write_idx_band + 1 ) % hSpatParamRendCom->dirac_md_buffer_length; + if ( idx_lfe < ( hDirAC->hOutSetup.num_lfe - 1 ) ) + { + idx_lfe++; + } + } + else if ( ( hDirAC->hOutSetup.separateChannelEnabled ) && ( hDirAC->hOutSetup.separateChannelIndex == ch ) ) + { + /* The separated channel is already set to output_f[hOutSetup.separateChannelIndex]. Thus, the separated + * channel is combined with the synthesized channels here. */ + } + else + { + /* open CLDFB buffer up to CLDFB_NO_CHANNELS_MAX bands for 48kHz */ + for ( i = 0; i < hDirAC->subframe_nbslots[subframe_idx]; i++ ) + { + RealBuffer[i] = Cldfb_RealBuffer[idx_in][i]; + ImagBuffer[i] = Cldfb_ImagBuffer[idx_in][i]; + } + cldfbSynthesis( RealBuffer, ImagBuffer, &( output_f[ch][index_slot * hDirAC->num_freq_bands] ), hDirAC->num_freq_bands * hDirAC->subframe_nbslots[subframe_idx], st_ivas->cldfbSynDec[idx_in] ); + idx_in++; + } } } } + hDirAC->slots_rendered += hDirAC->subframe_nbslots[subframe_idx]; + hDirAC->subframes_rendered++; - /* update buffer write index */ - hSpatParamRendCom->dirac_bs_md_write_idx = ( hSpatParamRendCom->dirac_bs_md_write_idx + MAX_PARAM_SPATIAL_SUBFRAMES ) % hSpatParamRendCom->dirac_md_buffer_length; + pop_wmops(); return; } /*------------------------------------------------------------------------- - * ivas_dirac_dec_set_md_map() + * compute_hoa_encoder_mtx() + * * - * Set metadata index mapping for DirAC *------------------------------------------------------------------------*/ -void ivas_dirac_dec_set_md_map( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ - const int16_t nCldfbTs /* i : number of CLDFB time slots */ -) +void compute_hoa_encoder_mtx( + const float *azimuth, + const float *elevation, + float *response, + const int16_t num_responses, + const int16_t ambisonics_order ) { - int16_t num_slots_in_subfr; - DIRAC_DEC_HANDLE hDirAC; - SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom; - - hDirAC = st_ivas->hDirAC; - hSpatParamRendCom = st_ivas->hSpatParamRendCom; -#ifdef DEBUGGING - assert( hDirAC ); - assert( hSpatParamRendCom ); -#endif - - /* adapt subframes */ - hSpatParamRendCom->num_slots = nCldfbTs; - hSpatParamRendCom->slots_rendered = 0; - num_slots_in_subfr = CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES; - hSpatParamRendCom->subframes_rendered = 0; - - ivas_jbm_dec_get_adapted_subframes( nCldfbTs, hSpatParamRendCom->subframe_nbslots, &hSpatParamRendCom->nb_subframes ); - - /* set mapping according to dirac_read_idx */ - - set_s( hSpatParamRendCom->render_to_md_map, 0, MAX_JBM_SUBFRAMES_5MS * JBM_CLDFB_SLOTS_IN_SUBFRAME ); + int16_t k, num_sh; -#ifdef FIX_470_MASA_JBM_EXT - if ( st_ivas->ivas_format == MASA_FORMAT ) - { - ivas_jbm_dec_get_md_map_even_spacing( DEFAULT_JBM_CLDFB_TIMESLOTS, nCldfbTs, num_slots_in_subfr, 0, hSpatParamRendCom->dirac_md_buffer_length, hSpatParamRendCom->render_to_md_map ); - } - else if ( hDirAC->hConfig == NULL || hDirAC->hConfig->dec_param_estim == 0 ) -#else - if ( hDirAC->hConfig == NULL || hDirAC->hConfig->dec_param_estim == 0 ) -#endif - { - ivas_jbm_dec_get_md_map( DEFAULT_JBM_CLDFB_TIMESLOTS, nCldfbTs, num_slots_in_subfr, 0, hSpatParamRendCom->dirac_md_buffer_length, hSpatParamRendCom->render_to_md_map ); - } - else - { - ivas_jbm_dec_get_md_map( DEFAULT_JBM_CLDFB_TIMESLOTS, nCldfbTs, num_slots_in_subfr, hSpatParamRendCom->dirac_read_idx, hSpatParamRendCom->dirac_md_buffer_length, hSpatParamRendCom->render_to_md_map ); - } + num_sh = ivas_sba_get_nchan( ambisonics_order, 0 ); - if ( hDirAC->hConfig == NULL || hDirAC->hConfig->dec_param_estim == 0 ) + for ( k = 0; k < num_responses; k++ ) { - float tmp; - int16_t sf_idx, slot_idx, slot_idx_abs; - - slot_idx_abs = 0; - for ( sf_idx = 0; sf_idx < hSpatParamRendCom->nb_subframes; sf_idx++ ) - { - tmp = 0.0f; - for ( slot_idx = 0; slot_idx < hSpatParamRendCom->subframe_nbslots[sf_idx]; slot_idx++ ) - { - tmp += (float) hSpatParamRendCom->render_to_md_map[slot_idx_abs]; - slot_idx_abs++; - } - hSpatParamRendCom->render_to_md_map[sf_idx] = ( (int16_t) roundf( tmp / (float) hSpatParamRendCom->subframe_nbslots[sf_idx] ) + hSpatParamRendCom->dirac_read_idx ) % hSpatParamRendCom->dirac_md_buffer_length; - } - - set_s( &hSpatParamRendCom->render_to_md_map[hSpatParamRendCom->nb_subframes], 0, MAX_JBM_SUBFRAMES_5MS * JBM_CLDFB_SLOTS_IN_SUBFRAME - hSpatParamRendCom->nb_subframes ); + ivas_dirac_dec_get_response( (const int16_t) azimuth[k], (const int16_t) elevation[k], &response[k * num_sh], ambisonics_order ); } return; @@ -1546,966 +3236,1138 @@ void ivas_dirac_dec_set_md_map( /*------------------------------------------------------------------------- - * ivas_dirac_dec() + * ivas_dirac_dec_get_frequency_axis() * - * DirAC decoding process + * DirAC decoding initialization *------------------------------------------------------------------------*/ -void ivas_dirac_dec( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ - float output_f[][L_FRAME48k], /* i/o: synthesized core-coder transport channels/DirAC output */ - const int16_t nchan_transport /* i : number of transport channels */ -) +void ivas_dirac_dec_get_frequency_axis( + float *frequency_axis, + const int32_t output_Fs, + const int16_t num_freq_bands ) { - int16_t subframe_idx; - float *output_f_local[MAX_OUTPUT_CHANNELS]; - float cng_td_buffer[L_FRAME16k]; - int16_t nchan_out, n, n_samples_sf; - SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom; - - hSpatParamRendCom = st_ivas->hSpatParamRendCom; - nchan_out = st_ivas->hIntSetup.nchan_out_woLFE + st_ivas->hIntSetup.num_lfe; + int16_t k; + float const_part; - n_samples_sf = JBM_CLDFB_SLOTS_IN_SUBFRAME * hSpatParamRendCom->slot_size; - - for ( n = 0; n < nchan_out; n++ ) + /* calc cldfb frequency axis */ + const_part = (float) output_Fs / ( 2.0f * (float) num_freq_bands ); + for ( k = 0; k < num_freq_bands; ++k ) { - output_f_local[n] = &output_f[n][0]; + frequency_axis[k] = ( (float) k + 0.5f ) * const_part; } - for ( n = 0; n < nchan_transport; n++ ) - { - st_ivas->hTcBuffer->tc[n] = output_f[n]; - } + return; +} - if ( st_ivas->nchan_transport == 1 && st_ivas->hSCE[0]->hCoreCoder[0] != NULL && st_ivas->hSCE[0]->hCoreCoder[0]->cna_dirac_flag && st_ivas->ivas_format != SBA_FORMAT ) + +/*------------------------------------------------------------------------- + * Local functions + *-------------------------------------------------------------------------*/ + +static void initDiffuseResponses( + float *diffuse_response_function, + const int16_t num_channels, + AUDIO_CONFIG output_config, + IVAS_OUTPUT_SETUP hOutSetup, + const int16_t ambisonics_order, + const IVAS_FORMAT ivas_format, + int16_t *num_ele_spk_no_diffuse_rendering, + AUDIO_CONFIG transport_config ) +{ + int16_t i, l, k, idx, num_horizontal_speakers; + *num_ele_spk_no_diffuse_rendering = 0; + + if ( output_config == AUDIO_CONFIG_MONO ) { - Decoder_State *st = st_ivas->hSCE[0]->hCoreCoder[0]; - st_ivas->hTcBuffer->tc[nchan_transport] = &cng_td_buffer[0]; - generate_masking_noise_lb_dirac( st->hFdCngDec->hFdCngCom, st_ivas->hTcBuffer->tc[1], DEFAULT_JBM_CLDFB_TIMESLOTS, st->cna_dirac_flag && st->flag_cna ); + diffuse_response_function[0] = 1.0f; + diffuse_response_function[1] = inv_sqrt( 3.0f ); } + else if ( !( output_config == AUDIO_CONFIG_FOA || output_config == AUDIO_CONFIG_HOA2 || output_config == AUDIO_CONFIG_HOA3 ) ) + { + /* set diffuse response function */ + if ( ivas_format == MC_FORMAT && ( transport_config == AUDIO_CONFIG_5_1 || transport_config == AUDIO_CONFIG_7_1 ) && output_config == AUDIO_CONFIG_5_1_4 ) + { + num_horizontal_speakers = num_channels - NUM_ELEVATED_SPEAKERS; - ivas_dirac_dec_set_md_map( st_ivas, DEFAULT_JBM_CLDFB_TIMESLOTS ); + mvr2r( diffuse_response_CICP6, diffuse_response_function, num_horizontal_speakers ); + set_zero( &diffuse_response_function[num_horizontal_speakers], NUM_ELEVATED_SPEAKERS ); + *num_ele_spk_no_diffuse_rendering = NUM_ELEVATED_SPEAKERS; + } + else if ( ivas_format == MC_FORMAT && ( transport_config == AUDIO_CONFIG_5_1 || transport_config == AUDIO_CONFIG_7_1 ) && output_config == AUDIO_CONFIG_7_1_4 ) + { + num_horizontal_speakers = num_channels - NUM_ELEVATED_SPEAKERS; - for ( subframe_idx = 0; subframe_idx < MAX_PARAM_SPATIAL_SUBFRAMES; subframe_idx++ ) - { - ivas_dirac_dec_render_sf( st_ivas, output_f_local, nchan_transport, NULL, NULL ); - for ( n = 0; n < nchan_out; n++ ) + set_f( diffuse_response_function, sqrtf( 1.f / ( (float) num_horizontal_speakers ) ), num_horizontal_speakers ); + set_zero( &diffuse_response_function[num_horizontal_speakers], NUM_ELEVATED_SPEAKERS ); + *num_ele_spk_no_diffuse_rendering = NUM_ELEVATED_SPEAKERS; + } +#ifdef MASA_AND_OBJECTS + else if ( ( ivas_format == MASA_FORMAT || ivas_format == MASA_ISM_FORMAT || ivas_format == MC_FORMAT ) && output_config == AUDIO_CONFIG_5_1 && num_channels == 5 ) +#else + else if ( ( ivas_format == MASA_FORMAT || ivas_format == MC_FORMAT ) && output_config == AUDIO_CONFIG_5_1 && num_channels == 5 ) +#endif + { + mvr2r( diffuse_response_CICP6, diffuse_response_function, num_channels ); + } +#ifdef MASA_AND_OBJECTS + else if ( ( ivas_format == MASA_FORMAT || ivas_format == MASA_ISM_FORMAT || ivas_format == MC_FORMAT ) && ( output_config == AUDIO_CONFIG_5_1_2 ) && ( num_channels == 7 ) ) +#else + else if ( ( ivas_format == MASA_FORMAT || ivas_format == MC_FORMAT ) && output_config == AUDIO_CONFIG_5_1_2 && num_channels == 7 ) +#endif + { + mvr2r( diffuse_response_CICP14, diffuse_response_function, num_channels ); + } +#ifdef MASA_AND_OBJECTS + else if ( ( ivas_format == MASA_FORMAT || ivas_format == MASA_ISM_FORMAT || ivas_format == MC_FORMAT ) && ( output_config == AUDIO_CONFIG_5_1_4 ) && ( num_channels == 9 ) ) +#else + else if ( ( ivas_format == MASA_FORMAT || ivas_format == MC_FORMAT ) && ( output_config == AUDIO_CONFIG_5_1_4 ) && ( num_channels == 9 ) ) +#endif + { + mvr2r( diffuse_response_CICP16, diffuse_response_function, num_channels ); + } +#ifdef MASA_AND_OBJECTS + else if ( ( ivas_format == MASA_FORMAT || ivas_format == MASA_ISM_FORMAT || ivas_format == MC_FORMAT ) && ( output_config == AUDIO_CONFIG_LS_CUSTOM ) ) +#else + else if ( ( ivas_format == MASA_FORMAT || ivas_format == MC_FORMAT ) && ( output_config == AUDIO_CONFIG_LS_CUSTOM ) ) +#endif { - output_f_local[n] += n_samples_sf; + if ( transport_config == AUDIO_CONFIG_5_1 || transport_config == AUDIO_CONFIG_7_1 ) + { + /* Detect loudspeakers with elevation */ + for ( i = 0, num_horizontal_speakers = 0; i < num_channels; i++ ) + { + if ( fabsf( hOutSetup.ls_elevation[i] ) <= 5.f ) + { + num_horizontal_speakers++; + diffuse_response_function[i] = 1.f; + } + else + { + *num_ele_spk_no_diffuse_rendering += 1; + diffuse_response_function[i] = 0.f; + } + } + /* Diffuse only to horizontal plane if enough loudspeakers */ + if ( num_horizontal_speakers > 2 ) + { + for ( i = 0; i < num_channels; i++ ) + { + diffuse_response_function[i] *= sqrtf( 1.f / (float) num_horizontal_speakers ); + } + } + else + { + *num_ele_spk_no_diffuse_rendering = 0; + set_f( diffuse_response_function, sqrtf( 1.f / (float) num_channels ), num_channels ); + } + } + else + { + set_f( diffuse_response_function, sqrtf( 1.f / (float) num_channels ), num_channels ); + } + } + else + { + set_f( diffuse_response_function, sqrtf( 1.f / (float) num_channels ), num_channels ); } - } - - if ( st_ivas->hDirAC->hConfig->dec_param_estim == 1 ) - { - hSpatParamRendCom->dirac_read_idx = ( hSpatParamRendCom->dirac_read_idx + DEFAULT_JBM_CLDFB_TIMESLOTS ) % hSpatParamRendCom->dirac_md_buffer_length; } else { - hSpatParamRendCom->dirac_read_idx = ( hSpatParamRendCom->dirac_read_idx + DEFAULT_JBM_SUBFRAMES_5MS ) % hSpatParamRendCom->dirac_md_buffer_length; - } - - for ( n = 0; n < nchan_transport; n++ ) - { - st_ivas->hTcBuffer->tc[n] = NULL; - } - - if ( st_ivas->nchan_transport == 1 && st_ivas->hSCE[0]->hCoreCoder[0] != NULL && st_ivas->hSCE[0]->hCoreCoder[0]->cna_dirac_flag && st_ivas->ivas_format != SBA_FORMAT ) - { - st_ivas->hTcBuffer->tc[nchan_transport] = NULL; + idx = 0; + for ( l = 0; l <= ambisonics_order; l++ ) + { + for ( k = 0; k < ( 2 * l + 1 ); k++ ) + { + diffuse_response_function[idx++] = inv_sqrt( 2.0f * l + 1.0f ); + } + } } return; } -/*------------------------------------------------------------------------- - * ivas_dirac_dec_render() - * - * DirAC decoding renderer process - *------------------------------------------------------------------------*/ - -void ivas_dirac_dec_render( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ - const int16_t nchan_transport, /* i : number of transport channels */ - const uint16_t nSamplesAsked, /* i : number of CLDFB slots requested */ - uint16_t *nSamplesRendered, /* o : number of CLDFB slots rendered */ - uint16_t *nSamplesAvailable, /* o : number of CLDFB slots still to render */ - float *output_f[] /* o : rendered time signal */ -) +static void protoSignalComputation_shd( + float RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], + float ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], + float *proto_direct_buffer_f, + float *proto_diffuse_buffer_f, + float *reference_power, + const int16_t slot_index, + const int16_t num_inputs, + const int16_t num_outputs_diff, + const int16_t num_freq_bands, + float *p_Rmat ) { - int16_t slots_to_render, first_sf, last_sf, subframe_idx; - uint16_t slot_size, n_samples_sf, ch, nchan_intern; - SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom; - float *output_f_local[MAX_OUTPUT_CHANNELS]; + int16_t l, k; + float *p_proto_direct_buffer; + float *p_proto_diffuse_buffer; + int16_t Rmat_k[4]; + float W_real, W_imag; + float Y_real, Y_imag; + float *p_k[4]; - hSpatParamRendCom = st_ivas->hSpatParamRendCom; + k = 0; /* to avoid compilation warning */ - nchan_intern = st_ivas->hIntSetup.nchan_out_woLFE + st_ivas->hIntSetup.num_lfe; -#ifdef DEBUGGING - assert( hSpatParamRendCom ); -#endif - for ( ch = 0; ch < nchan_intern; ch++ ) + p_proto_direct_buffer = proto_direct_buffer_f + slot_index * 2 * num_freq_bands * num_inputs; + p_proto_diffuse_buffer = proto_diffuse_buffer_f + slot_index * 2 * num_freq_bands * num_outputs_diff; + + if ( num_inputs == 1 ) { - output_f_local[ch] = output_f[ch]; + for ( l = 0; l < num_freq_bands; l++ ) + { + p_proto_direct_buffer[2 * l] = RealBuffer[0][0][l]; + p_proto_direct_buffer[2 * l + 1] = ImagBuffer[0][0][l]; + } } - slot_size = NS2SA( st_ivas->hDecoderConfig->output_Fs, CLDFB_SLOT_NS ); + else if ( num_inputs == 2 ) + { + if ( p_Rmat != 0 ) + { + assert( num_inputs == 4 && "This code block should never be run with num_inputs != 4!" ); - /* loop for synthesis, assume we always have to render in multiples of 5ms subframes with spills */ - slots_to_render = min( hSpatParamRendCom->num_slots - hSpatParamRendCom->slots_rendered, nSamplesAsked / slot_size ); - *nSamplesRendered = slots_to_render * slot_size; - first_sf = hSpatParamRendCom->subframes_rendered; - last_sf = first_sf; + for ( l = 0; l < num_freq_bands; l++ ) + { + W_real = RealBuffer[0][0][l] + RealBuffer[1][0][l]; + W_imag = ImagBuffer[0][0][l] + ImagBuffer[1][0][l]; - while ( slots_to_render > 0 ) - { - slots_to_render -= hSpatParamRendCom->subframe_nbslots[last_sf]; - last_sf++; - } + Y_real = RealBuffer[0][0][l] - RealBuffer[1][0][l]; + Y_imag = ImagBuffer[0][0][l] - ImagBuffer[1][0][l]; -#ifdef DEBUGGING - assert( slots_to_render == 0 ); -#endif - for ( subframe_idx = first_sf; subframe_idx < last_sf; subframe_idx++ ) - { - ivas_dirac_dec_render_sf( st_ivas, output_f_local, nchan_transport, NULL, NULL ); - n_samples_sf = hSpatParamRendCom->subframe_nbslots[subframe_idx] * hSpatParamRendCom->slot_size; - for ( ch = 0; ch < nchan_intern; ch++ ) + p_proto_direct_buffer[2 * l] = W_real; + p_proto_direct_buffer[2 * l + 1] = W_imag; + p_proto_direct_buffer[2 * num_freq_bands + 2 * l] = p_Rmat[0] * Y_real; + p_proto_direct_buffer[2 * num_freq_bands + 2 * l + 1] = p_Rmat[0] * Y_imag; + } + } + else { - output_f_local[ch] += n_samples_sf; + for ( l = 0; l < num_freq_bands; l++ ) + { + W_real = RealBuffer[0][0][l] + RealBuffer[1][0][l]; + W_imag = ImagBuffer[0][0][l] + ImagBuffer[1][0][l]; + + p_proto_direct_buffer[2 * l] = W_real; + p_proto_direct_buffer[2 * l + 1] = W_imag; + { + p_proto_direct_buffer[2 * num_freq_bands + 2 * l] = RealBuffer[0][0][l] - RealBuffer[1][0][l]; + p_proto_direct_buffer[2 * num_freq_bands + 2 * l + 1] = ImagBuffer[0][0][l] - ImagBuffer[1][0][l]; + } + } } } - - if ( hSpatParamRendCom->slots_rendered == hSpatParamRendCom->num_slots ) + else if ( num_inputs >= 4 ) { - if ( st_ivas->hDirAC->hConfig->dec_param_estim == 1 ) + p_k[0] = p_proto_direct_buffer; + p_k[1] = p_proto_direct_buffer + 2 * num_freq_bands; + p_k[2] = p_proto_direct_buffer + 4 * num_freq_bands; + p_k[3] = p_proto_direct_buffer + 6 * num_freq_bands; + Rmat_k[0] = 0; + Rmat_k[1] = 1; + Rmat_k[2] = 2; + Rmat_k[3] = 0; + + if ( p_Rmat != 0 ) { - hSpatParamRendCom->dirac_read_idx = ( hSpatParamRendCom->dirac_read_idx + DEFAULT_JBM_CLDFB_TIMESLOTS ) % hSpatParamRendCom->dirac_md_buffer_length; + assert( num_inputs == 4 && "This code block should never be run with num_inputs != 4!" ); + + for ( l = 0; l < num_freq_bands; l++ ) + { + *( p_k[0] ) = RealBuffer[0][0][l]; + reference_power[l + num_freq_bands] = *( p_k[0] ) * *( p_k[0] ); + p_k[0]++; + *( p_k[0] ) = ImagBuffer[0][0][l]; + reference_power[l + num_freq_bands] += *( p_k[0] ) * *( p_k[0] ); + p_k[0]++; + reference_power[l] = 0.5f * reference_power[l + num_freq_bands]; + + for ( k = 1; k < 4; k++ ) + { + *( p_k[k] ) = p_Rmat[3 * Rmat_k[k] + 1] * RealBuffer[1][0][l] + p_Rmat[3 * Rmat_k[k] + 2] * RealBuffer[2][0][l] + p_Rmat[3 * Rmat_k[k] + 0] * RealBuffer[3][0][l]; + reference_power[l + ( k + 1 ) * num_freq_bands] = *( p_k[k] ) * *( p_k[k] ); + p_k[k]++; + *( p_k[k] ) = p_Rmat[3 * Rmat_k[k] + 1] * ImagBuffer[1][0][l] + p_Rmat[3 * Rmat_k[k] + 2] * ImagBuffer[2][0][l] + p_Rmat[3 * Rmat_k[k] + 0] * ImagBuffer[3][0][l]; + reference_power[l + ( k + 1 ) * num_freq_bands] += *( p_k[k] ) * *( p_k[k] ); + p_k[k]++; + reference_power[l] += 0.5f * ( reference_power[l + ( k + 1 ) * num_freq_bands] ); + } + + for ( k = 1; k < 4; k++ ) + { + RealBuffer[k][0][l] = p_proto_direct_buffer[k * 2 * num_freq_bands + 2 * l]; + ImagBuffer[k][0][l] = p_proto_direct_buffer[k * 2 * num_freq_bands + 2 * l + 1]; + } + } } else { - hSpatParamRendCom->dirac_read_idx = ( hSpatParamRendCom->dirac_read_idx + DEFAULT_JBM_SUBFRAMES_5MS ) % hSpatParamRendCom->dirac_md_buffer_length; + set_zero( reference_power, num_freq_bands ); + for ( k = 0; k < 4; k++ ) + { + for ( l = 0; l < num_freq_bands; l++ ) + { + p_proto_direct_buffer[k * 2 * num_freq_bands + 2 * l] = RealBuffer[k][0][l]; + p_proto_direct_buffer[k * 2 * num_freq_bands + 2 * l + 1] = ImagBuffer[k][0][l]; + reference_power[l + ( k + 1 ) * num_freq_bands] = RealBuffer[k][0][l] * RealBuffer[k][0][l] + ImagBuffer[k][0][l] * ImagBuffer[k][0][l]; + reference_power[l] += 0.5f * ( reference_power[l + ( k + 1 ) * num_freq_bands] ); + } + } + } + + /* Additional transport channels = planar SBA components of degree higher than 1*/ + for ( ; k < num_inputs; k++ ) + { + for ( l = 0; l < num_freq_bands; l++ ) + { + p_proto_direct_buffer[k * 2 * num_freq_bands + 2 * l] = RealBuffer[k][0][l]; + p_proto_direct_buffer[k * 2 * num_freq_bands + 2 * l + 1] = ImagBuffer[k][0][l]; + } } } - *nSamplesAvailable = ( hSpatParamRendCom->num_slots - hSpatParamRendCom->slots_rendered ) * slot_size; + + /*Copy direct to diffuse proto*/ + mvr2r( p_proto_direct_buffer, p_proto_diffuse_buffer, 2 * num_freq_bands * min( num_outputs_diff, num_inputs ) ); + + if ( num_inputs == 1 ) + { + /* Add comfort noise addition (CNA) to diffuse proto only*/ + for ( l = 0; l < num_freq_bands; l++ ) + { + p_proto_diffuse_buffer[2 * l] += RealBuffer[1][0][l]; + p_proto_diffuse_buffer[2 * l + 1] += ImagBuffer[1][0][l]; + } + } return; } -/*------------------------------------------------------------------------- - * ivas_dirac_dec() - * - * DirAC decoding process - *------------------------------------------------------------------------*/ - -void ivas_dirac_dec_render_sf( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ - float *output_f[], /* i/o: synthesized core-coder transport channels/DirAC output */ - const int16_t nchan_transport, /* i : number of transport channels */ - float *pppQMfFrame_ts_re[IVAS_MAX_FB_MIXER_IN_CH][CLDFB_NO_COL_MAX], - float *pppQMfFrame_ts_im[IVAS_MAX_FB_MIXER_IN_CH][CLDFB_NO_COL_MAX] ) +static void protoSignalComputation1( + float RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], + float ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], + float *proto_frame_f, + float *proto_direct_buffer_f, + float *reference_power, + float *proto_power_smooth, + const int16_t slot_index, + const int16_t num_outputs_diff, + const int16_t num_freq_bands ) { - int16_t i, ch, idx_in, idx_lfe; - DIRAC_DEC_HANDLE hDirAC; - DIRAC_REND_HANDLE hDirACRend; - float dirEne; - float surCohEner; - float surCohRatio[CLDFB_NO_CHANNELS_MAX]; - int16_t subframe_idx; - int16_t slot_idx, index_slot; - int16_t hodirac_flag; - float *p_Rmat; - int16_t slot_idx_start, slot_idx_start_cldfb_synth, md_idx; + int16_t l, k; + float *p_proto_buffer; - /*CLDFB: last output channels reserved to LFT for CICPx*/ - float Cldfb_RealBuffer[MAX_OUTPUT_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; - float Cldfb_ImagBuffer[MAX_OUTPUT_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; -#ifdef SPLIT_REND_WITH_HEAD_ROT - float Cldfb_RealBuffer_Binaural[MAX_HEAD_ROT_POSES][BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; - float Cldfb_ImagBuffer_Binaural[MAX_HEAD_ROT_POSES][BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; -#else - float Cldfb_RealBuffer_Binaural[BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; - float Cldfb_ImagBuffer_Binaural[BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; -#endif + p_proto_buffer = proto_direct_buffer_f + slot_index * 2 * num_freq_bands; - int16_t index, num_freq_bands; + for ( l = 0; l < num_freq_bands; l++ ) + { + reference_power[l] = RealBuffer[0][0][l] * RealBuffer[0][0][l] + ImagBuffer[0][0][l] * ImagBuffer[0][0][l]; + proto_power_smooth[l] += reference_power[l]; + p_proto_buffer[2 * l] = RealBuffer[0][0][l]; + p_proto_buffer[2 * l + 1] = ImagBuffer[0][0][l]; - /* local copies of azi, ele, diffuseness */ - int16_t azimuth[CLDFB_NO_CHANNELS_MAX]; - int16_t elevation[CLDFB_NO_CHANNELS_MAX]; - float diffuseness_vector[CLDFB_NO_CHANNELS_MAX]; + for ( k = 0; k < num_outputs_diff; k++ ) + { + proto_frame_f[2 * k * num_freq_bands + 2 * l] = RealBuffer[0][0][l]; + proto_frame_f[2 * k * num_freq_bands + 2 * l + 1] = ImagBuffer[0][0][l]; + } + } - DIRAC_DEC_STACK_MEM DirAC_mem; - float *reference_power, *reference_power_smooth; - float *onset_filter, *onset_filter_subframe, *p_onset_filter = NULL; - uint16_t coherence_flag; - SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom; + return; +} - push_wmops( "ivas_dirac_dec_render" ); - /* Initialize aux buffers */ - hDirAC = st_ivas->hDirAC; - hDirACRend = st_ivas->hDirACRend; - hSpatParamRendCom = st_ivas->hSpatParamRendCom; +static void protoSignalComputation2( + float RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], + float ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], + float *proto_frame_f, + float *proto_direct_buffer_f, + float *reference_power, + float *proto_power_smooth, + const int16_t isloudspeaker, + const int16_t slot_index, + const int16_t num_freq_bands, + MASA_STEREO_TYPE_DETECT *stereo_type_detect ) +{ + int16_t l; + float *p_proto_buffer; + float Real_aux, Imag_aux; - DirAC_mem = hDirACRend->stack_mem; + float left_bb_power, right_bb_power, total_bb_power, lr_bb_power; + float lr_total_bb_ratio; + float a, b; - reference_power = DirAC_mem.reference_power; - reference_power_smooth = DirAC_mem.reference_power + hSpatParamRendCom->num_freq_bands; - onset_filter = DirAC_mem.onset_filter; -#ifdef FIX_614_ADD_TO_NULL_PTR_DIRAC_SETUP - onset_filter_subframe = ( DirAC_mem.onset_filter == NULL ) ? NULL : DirAC_mem.onset_filter + hSpatParamRendCom->num_freq_bands; -#else - onset_filter_subframe = DirAC_mem.onset_filter + hSpatParamRendCom->num_freq_bands; -#endif + float left_hi_power, right_hi_power, total_hi_power, lr_hi_power; + float lr_total_hi_ratio; + float a2, b2; - hodirac_flag = ivas_get_hodirac_flag( st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->sba_analysis_order ); + float sum_power; + float sum_total_ratio[MASA_SUM_FREQ_RANGE_BINS]; + float min_sum_total_ratio; + float min_sum_total_ratio_db; - if ( st_ivas->hQMetaData != NULL && st_ivas->ivas_format != SBA_FORMAT ) + float RealSubtract, ImagSubtract; + + float interpolatorSpaced = 0.0f; + float interpolatorDmx = 1.0f; + + int16_t dipole_freq_range[2]; + float tempSpaced, tempDmx; + + if ( isloudspeaker ) { - coherence_flag = st_ivas->hQMetaData->coherence_flag; + p_proto_buffer = proto_direct_buffer_f + slot_index * 2 * num_freq_bands * 3; + + for ( l = 0; l < num_freq_bands; l++ ) + { + float Left_power; + float Right_power; + Real_aux = RealBuffer[0][0][l] + RealBuffer[1][0][l]; + Imag_aux = ImagBuffer[0][0][l] + ImagBuffer[1][0][l]; + + Left_power = RealBuffer[0][0][l] * RealBuffer[0][0][l] + ImagBuffer[0][0][l] * ImagBuffer[0][0][l]; + Right_power = RealBuffer[1][0][l] * RealBuffer[1][0][l] + ImagBuffer[1][0][l] * ImagBuffer[1][0][l]; + + reference_power[l] = Left_power + Right_power; + proto_power_smooth[l] += Real_aux * Real_aux + Imag_aux * Imag_aux; + + p_proto_buffer[2 * l] = Real_aux; + p_proto_buffer[2 * l + 1] = Imag_aux; + proto_power_smooth[l + num_freq_bands] += RealBuffer[0][0][l] * RealBuffer[0][0][l] + ImagBuffer[0][0][l] * ImagBuffer[0][0][l]; + p_proto_buffer[2 * num_freq_bands + 2 * l] = RealBuffer[0][0][l]; + p_proto_buffer[2 * num_freq_bands + 2 * l + 1] = ImagBuffer[0][0][l]; + + proto_power_smooth[l + 2 * num_freq_bands] += RealBuffer[1][0][l] * RealBuffer[1][0][l]; + proto_power_smooth[l + 2 * num_freq_bands] += ImagBuffer[1][0][l] * ImagBuffer[1][0][l]; + p_proto_buffer[4 * num_freq_bands + 2 * l] = RealBuffer[1][0][l]; + p_proto_buffer[4 * num_freq_bands + 2 * l + 1] = ImagBuffer[1][0][l]; + + proto_frame_f[2 * l] = Real_aux; + proto_frame_f[2 * l + 1] = Imag_aux; + + proto_frame_f[2 * num_freq_bands + 2 * l] = RealBuffer[0][0][l]; + proto_frame_f[2 * num_freq_bands + 2 * l + 1] = ImagBuffer[0][0][l]; + proto_frame_f[4 * num_freq_bands + 2 * l] = RealBuffer[1][0][l]; + proto_frame_f[4 * num_freq_bands + 2 * l + 1] = ImagBuffer[1][0][l]; + } } - else + else if ( stereo_type_detect != NULL ) { - coherence_flag = 0; - } + p_proto_buffer = proto_direct_buffer_f + slot_index * 2 * num_freq_bands * 2; -#ifdef DEBUG_MODE_DIRAC - { - int16_t n, tmp[IVAS_SPAR_MAX_CH * L_FRAME48k]; - char file_name[50] = { 0 }; - const int16_t output_frame = st_ivas->hDecoderConfig->output_Fs / FRAMES_PER_SEC; + left_bb_power = 0.0f; + right_bb_power = 0.0f; + total_bb_power = 0.0f; - for ( n = 0; n < nchan_transport; n++ ) + left_hi_power = 0.0f; + right_hi_power = 0.0f; + total_hi_power = 0.0f; + + dipole_freq_range[0] = stereo_type_detect->dipole_freq_range[0]; + dipole_freq_range[1] = stereo_type_detect->dipole_freq_range[1]; + + a = 0.01f; /* Temporal smoothing coefficient */ + b = 1.0f - a; /* Temporal smoothing coefficient */ + a2 = 0.1f; /* Temporal smoothing coefficient */ + b2 = 1.0f - a2; /* Temporal smoothing coefficient */ + + if ( stereo_type_detect->interpolator > 0 ) { - for ( i = 0; i < output_frame; i++ ) + if ( stereo_type_detect->type_change_direction == MASA_STEREO_SPACED_MICS ) { - tmp[nchan_transport * i + n] = (int16_t) ( output_f[n][i] + 0.5f ); + interpolatorSpaced = ( (float) ( stereo_type_detect->interpolator ) ) / ( (float) MASA_STEREO_INTERPOLATION_SLOTS ); + interpolatorDmx = 1.0f - interpolatorSpaced; + } + else + { + interpolatorDmx = ( (float) ( stereo_type_detect->interpolator ) ) / ( (float) MASA_STEREO_INTERPOLATION_SLOTS ); + interpolatorSpaced = 1.0f - interpolatorDmx; } } - sprintf( file_name, "./res/ivas_dirac_dec_DMX%d.%d.pcm", nchan_transport, (int16_t) ( output_frame * 0.05 ) ); - dbgwrite( tmp, sizeof( int16_t ), nchan_transport * output_frame, 1, file_name ); - } -#endif - /* Subframe loop */ - slot_idx_start = hSpatParamRendCom->slots_rendered; - slot_idx_start_cldfb_synth = 0; + for ( l = 0; l < num_freq_bands; l++ ) + { + float Left_power; + float Right_power; - subframe_idx = hSpatParamRendCom->subframes_rendered; - if ( hDirAC->hConfig->dec_param_estim == FALSE ) - { - md_idx = hSpatParamRendCom->render_to_md_map[subframe_idx]; - } - else - { - md_idx = hSpatParamRendCom->render_to_md_map[slot_idx_start]; - } - /* ToDo: Another workaround for self test BE */ + /* Compute sum signal */ + Real_aux = RealBuffer[0][0][l] + RealBuffer[1][0][l]; + Imag_aux = ImagBuffer[0][0][l] + ImagBuffer[1][0][l]; - /* copy parameters into local buffers*/ - if ( hDirAC->hConfig->dec_param_estim == FALSE ) - { - mvs2s( hSpatParamRendCom->azimuth[hSpatParamRendCom->render_to_md_map[subframe_idx]], azimuth, hSpatParamRendCom->num_freq_bands ); - mvs2s( hSpatParamRendCom->elevation[hSpatParamRendCom->render_to_md_map[subframe_idx]], elevation, hSpatParamRendCom->num_freq_bands ); - mvr2r( hSpatParamRendCom->diffuseness_vector[hSpatParamRendCom->render_to_md_map[subframe_idx]], diffuseness_vector, hSpatParamRendCom->num_freq_bands ); - } - else - { - set_zero( diffuseness_vector, hSpatParamRendCom->num_freq_bands ); - } + /* Compute reference power */ + Left_power = RealBuffer[0][0][l] * RealBuffer[0][0][l] + ImagBuffer[0][0][l] * ImagBuffer[0][0][l]; + Right_power = RealBuffer[1][0][l] * RealBuffer[1][0][l] + ImagBuffer[1][0][l] * ImagBuffer[1][0][l]; - if ( hDirACRend->synthesisConf != DIRAC_SYNTHESIS_GAIN_SHD ) - { - set_zero( reference_power_smooth, hSpatParamRendCom->num_freq_bands ); - } - else - { - set_zero( onset_filter_subframe, hSpatParamRendCom->num_freq_bands ); - } + reference_power[l] = Left_power + Right_power; - if ( st_ivas->hCombinedOrientationData && st_ivas->hCombinedOrientationData->enableCombinedOrientation[subframe_idx] ) - { - p_Rmat = &st_ivas->hCombinedOrientationData->Rmat[subframe_idx][0][0]; + left_bb_power += Left_power; + right_bb_power += Right_power; + total_bb_power += reference_power[l]; - if ( st_ivas->hCombinedOrientationData->shd_rot_max_order == 0 ) - { - num_freq_bands = hDirAC->band_grouping[hDirAC->hConfig->enc_param_start_band]; - if ( hDirAC->hConfig->dec_param_estim == FALSE ) + if ( l > MASA_HI_FREQ_START_BIN ) { - rotateAziEle_DirAC( azimuth, elevation, num_freq_bands, hSpatParamRendCom->num_freq_bands, p_Rmat ); + left_hi_power += Left_power; + right_hi_power += Right_power; + total_hi_power += reference_power[l]; } - } - } - else - { - p_Rmat = 0; - } - if ( hDirAC->hConfig->dec_param_estim == FALSE ) - { - /* compute response */ - if ( hDirACRend->synthesisConf != DIRAC_SYNTHESIS_GAIN_SHD ) - { - ivas_dirac_dec_compute_power_factors( hSpatParamRendCom->num_freq_bands, - diffuseness_vector, - hDirACRend->h_output_synthesis_psd_params.max_band_decorr, - hDirACRend->h_output_synthesis_psd_state.direct_power_factor, - hDirACRend->h_output_synthesis_psd_state.diffuse_power_factor ); + if ( l < min( num_freq_bands, MASA_SUM_FREQ_RANGE_BINS ) ) + { + sum_power = Real_aux * Real_aux + Imag_aux * Imag_aux; - if ( coherence_flag ) + stereo_type_detect->sum_power[l] = a * sum_power + b * stereo_type_detect->sum_power[l]; + stereo_type_detect->total_power[l] = a * reference_power[l] + b * stereo_type_detect->total_power[l]; + + sum_total_ratio[l] = stereo_type_detect->sum_power[l] / ( stereo_type_detect->total_power[l] + EPSILON ); + } + + if ( l == 0 ) + { + RealSubtract = RealBuffer[0][0][l] - RealBuffer[1][0][l]; + ImagSubtract = ImagBuffer[0][0][l] - ImagBuffer[1][0][l]; + stereo_type_detect->subtract_power_y += RealSubtract * RealSubtract + ImagSubtract * ImagSubtract; + } + + /* Compute protos (and their power) for direct sound rendering */ + + /* W prototype */ + if ( stereo_type_detect->interpolator > 0 ) { - for ( i = 0; i < hSpatParamRendCom->num_freq_bands; i++ ) + if ( l < ( dipole_freq_range[1] - 1 ) || l >= MASA_SUM_PROTO_START_BIN ) { - dirEne = hDirACRend->h_output_synthesis_psd_state.direct_power_factor[i]; - surCohEner = hDirACRend->h_output_synthesis_psd_state.diffuse_power_factor[i] * hSpatParamRendCom->surroundingCoherence[md_idx][i]; - hDirACRend->h_output_synthesis_psd_state.diffuse_power_factor[i] -= surCohEner; - hDirACRend->h_output_synthesis_psd_state.direct_power_factor[i] += surCohEner; - - surCohRatio[i] = surCohEner / ( 1e-12f + dirEne + surCohEner ); + Real_aux = interpolatorSpaced * 0.5f * Real_aux + interpolatorDmx * Real_aux; + Imag_aux = interpolatorSpaced * 0.5f * Imag_aux + interpolatorDmx * Imag_aux; + proto_power_smooth[l] += Real_aux * Real_aux + Imag_aux * Imag_aux; + p_proto_buffer[2 * l] = Real_aux; + p_proto_buffer[2 * l + 1] = Imag_aux; + } + else + { + tempSpaced = RealBuffer[0][0][l] * RealBuffer[0][0][l] + ImagBuffer[0][0][l] * ImagBuffer[0][0][l]; + tempDmx = Real_aux * Real_aux + Imag_aux * Imag_aux; + proto_power_smooth[l] += interpolatorSpaced * tempSpaced + interpolatorDmx * tempDmx; + p_proto_buffer[2 * l] = interpolatorSpaced * RealBuffer[0][0][l] + interpolatorDmx * Real_aux; + p_proto_buffer[2 * l + 1] = interpolatorSpaced * ImagBuffer[0][0][l] + interpolatorDmx * Imag_aux; + } + } + else if ( stereo_type_detect->masa_stereo_type == MASA_STEREO_SPACED_MICS ) + { + if ( l < ( dipole_freq_range[1] - 1 ) || l >= MASA_SUM_PROTO_START_BIN ) + { + Real_aux *= 0.5f; + Imag_aux *= 0.5f; + proto_power_smooth[l] += Real_aux * Real_aux + Imag_aux * Imag_aux; + p_proto_buffer[2 * l] = Real_aux; + p_proto_buffer[2 * l + 1] = Imag_aux; + } + else + { + proto_power_smooth[l] += RealBuffer[0][0][l] * RealBuffer[0][0][l] + ImagBuffer[0][0][l] * ImagBuffer[0][0][l]; + p_proto_buffer[2 * l] = RealBuffer[0][0][l]; + p_proto_buffer[2 * l + 1] = ImagBuffer[0][0][l]; } } else { - set_zero( surCohRatio, hSpatParamRendCom->num_freq_bands ); + proto_power_smooth[l] += Real_aux * Real_aux + Imag_aux * Imag_aux; + p_proto_buffer[2 * l] = Real_aux; + p_proto_buffer[2 * l + 1] = Imag_aux; } - } - else - { - ivas_dirac_dec_compute_gain_factors( hSpatParamRendCom->num_freq_bands, - hSpatParamRendCom->diffuseness_vector[md_idx], - hDirACRend->h_output_synthesis_psd_params.max_band_decorr, - hDirACRend->h_output_synthesis_psd_state.direct_power_factor, - hDirACRend->h_output_synthesis_psd_state.diffuse_power_factor ); - if ( coherence_flag ) + /* Y prototype */ + if ( stereo_type_detect->interpolator > 0 ) { - for ( i = 0; i < hSpatParamRendCom->num_freq_bands; i++ ) + if ( l < ( dipole_freq_range[0] ) ) { - surCohRatio[i] = hSpatParamRendCom->surroundingCoherence[md_idx][i]; + p_proto_buffer[2 * num_freq_bands + 2 * l] = interpolatorSpaced * p_proto_buffer[2 * l] + interpolatorDmx * ( RealBuffer[0][0][l] - RealBuffer[1][0][l] ); + p_proto_buffer[2 * num_freq_bands + 2 * l + 1] = interpolatorSpaced * p_proto_buffer[2 * l + 1] + interpolatorDmx * ( ImagBuffer[0][0][l] - ImagBuffer[1][0][l] ); + } + else if ( l < ( dipole_freq_range[1] ) ) + { + p_proto_buffer[2 * num_freq_bands + 2 * l] = interpolatorSpaced * ( ImagBuffer[0][0][l] - ImagBuffer[1][0][l] ) + interpolatorDmx * ( RealBuffer[0][0][l] - RealBuffer[1][0][l] ); + p_proto_buffer[2 * num_freq_bands + 2 * l + 1] = interpolatorSpaced * ( -( RealBuffer[0][0][l] - RealBuffer[1][0][l] ) ) + interpolatorDmx * ( ImagBuffer[0][0][l] - ImagBuffer[1][0][l] ); + } + else + { + p_proto_buffer[2 * num_freq_bands + 2 * l] = interpolatorSpaced * p_proto_buffer[2 * l] + interpolatorDmx * ( RealBuffer[0][0][l] - RealBuffer[1][0][l] ); + p_proto_buffer[2 * num_freq_bands + 2 * l + 1] = interpolatorSpaced * p_proto_buffer[2 * l + 1] + interpolatorDmx * ( ImagBuffer[0][0][l] - ImagBuffer[1][0][l] ); + } + proto_power_smooth[l + num_freq_bands] += p_proto_buffer[2 * num_freq_bands + 2 * l] * p_proto_buffer[2 * num_freq_bands + 2 * l] + p_proto_buffer[2 * num_freq_bands + 2 * l + 1] * p_proto_buffer[2 * num_freq_bands + 2 * l + 1]; + } + else if ( stereo_type_detect->masa_stereo_type == MASA_STEREO_SPACED_MICS ) + { + if ( l < ( dipole_freq_range[0] ) ) /* proto = W */ + { + p_proto_buffer[2 * num_freq_bands + 2 * l] = p_proto_buffer[2 * l]; + p_proto_buffer[2 * num_freq_bands + 2 * l + 1] = p_proto_buffer[2 * l + 1]; + proto_power_smooth[l + num_freq_bands] = proto_power_smooth[l]; + } + else if ( l < ( dipole_freq_range[1] ) ) /* proto = -i * (x1-x2) * eq */ + { + p_proto_buffer[2 * num_freq_bands + 2 * l] = ( ImagBuffer[0][0][l] - ImagBuffer[1][0][l] ); + p_proto_buffer[2 * num_freq_bands + 2 * l + 1] = -( RealBuffer[0][0][l] - RealBuffer[1][0][l] ); + proto_power_smooth[l + num_freq_bands] += p_proto_buffer[2 * num_freq_bands + 2 * l] * p_proto_buffer[2 * num_freq_bands + 2 * l] + p_proto_buffer[2 * num_freq_bands + 2 * l + 1] * p_proto_buffer[2 * num_freq_bands + 2 * l + 1]; + } + else /* proto = W */ + { + p_proto_buffer[2 * num_freq_bands + 2 * l] = p_proto_buffer[2 * l]; + p_proto_buffer[2 * num_freq_bands + 2 * l + 1] = p_proto_buffer[2 * l + 1]; + proto_power_smooth[l + num_freq_bands] = proto_power_smooth[l]; } } else { - set_zero( surCohRatio, hSpatParamRendCom->num_freq_bands ); + p_proto_buffer[2 * num_freq_bands + 2 * l] = RealBuffer[0][0][l] - RealBuffer[1][0][l]; + p_proto_buffer[2 * num_freq_bands + 2 * l + 1] = ImagBuffer[0][0][l] - ImagBuffer[1][0][l]; + proto_power_smooth[l + num_freq_bands] += p_proto_buffer[2 * num_freq_bands + 2 * l] * p_proto_buffer[2 * num_freq_bands + 2 * l] + p_proto_buffer[2 * num_freq_bands + 2 * l + 1] * p_proto_buffer[2 * num_freq_bands + 2 * l + 1]; } + + /* Compute protos for decorrelation */ + proto_frame_f[2 * l] = Real_aux; + proto_frame_f[2 * l + 1] = Imag_aux; + proto_frame_f[2 * num_freq_bands + 2 * l] = RealBuffer[0][0][l]; + proto_frame_f[2 * num_freq_bands + 2 * l + 1] = ImagBuffer[0][0][l]; + proto_frame_f[4 * num_freq_bands + 2 * l] = RealBuffer[1][0][l]; + proto_frame_f[4 * num_freq_bands + 2 * l + 1] = ImagBuffer[1][0][l]; } - if ( st_ivas->hCombinedOrientationData && st_ivas->hCombinedOrientationData->enableCombinedOrientation[subframe_idx] && st_ivas->hCombinedOrientationData->shd_rot_max_order == 1 ) + + if ( stereo_type_detect->interpolator > 0 ) { - ivas_dirac_dec_compute_directional_responses( hSpatParamRendCom, - hDirACRend, - st_ivas->hVBAPdata, - st_ivas->hMasa, - azimuth, - elevation, - md_idx, - surCohRatio, - st_ivas->hCombinedOrientationData->shd_rot_max_order, - p_Rmat, - hodirac_flag ); + stereo_type_detect->interpolator++; + if ( stereo_type_detect->interpolator == MASA_STEREO_INTERPOLATION_SLOTS ) + { + stereo_type_detect->interpolator = 0; + stereo_type_detect->current_stereo_type = stereo_type_detect->type_change_direction; + } } - else + + stereo_type_detect->left_bb_power = a * left_bb_power + b * stereo_type_detect->left_bb_power; + stereo_type_detect->right_bb_power = a * right_bb_power + b * stereo_type_detect->right_bb_power; + stereo_type_detect->total_bb_power = a * total_bb_power + b * stereo_type_detect->total_bb_power; + + lr_bb_power = ( stereo_type_detect->left_bb_power < stereo_type_detect->right_bb_power ) ? stereo_type_detect->left_bb_power : stereo_type_detect->right_bb_power; + lr_bb_power *= 2.0f; + lr_total_bb_ratio = 10.0f * log10f( lr_bb_power / ( stereo_type_detect->total_bb_power + EPSILON ) ); + + stereo_type_detect->left_hi_power = a2 * left_hi_power + b2 * stereo_type_detect->left_hi_power; + stereo_type_detect->right_hi_power = a2 * right_hi_power + b2 * stereo_type_detect->right_hi_power; + stereo_type_detect->total_hi_power = a2 * total_hi_power + b2 * stereo_type_detect->total_hi_power; + + lr_hi_power = ( stereo_type_detect->left_hi_power < stereo_type_detect->right_hi_power ) ? stereo_type_detect->left_hi_power : stereo_type_detect->right_hi_power; + lr_hi_power *= 2.0f; + lr_total_hi_ratio = 10.0f * log10f( lr_hi_power / ( stereo_type_detect->total_hi_power + EPSILON ) ); + + minimum( sum_total_ratio, min( num_freq_bands, MASA_SUM_FREQ_RANGE_BINS ), &min_sum_total_ratio ); + min_sum_total_ratio_db = 10.0f * log10f( min_sum_total_ratio ); + + stereo_type_detect->lr_total_bb_ratio_db = lr_total_bb_ratio; + stereo_type_detect->lr_total_hi_ratio_db = lr_total_hi_ratio; + stereo_type_detect->min_sum_total_ratio_db = min_sum_total_ratio_db; + + ivas_masa_stereotype_detection( stereo_type_detect ); + } + else + { + p_proto_buffer = proto_direct_buffer_f + slot_index * 2 * num_freq_bands * 2; + + for ( l = 0; l < num_freq_bands; l++ ) { - ivas_dirac_dec_compute_directional_responses( hSpatParamRendCom, - hDirACRend, - st_ivas->hVBAPdata, - st_ivas->hMasa, - azimuth, - elevation, - md_idx, - surCohRatio, - 0, - NULL, - hodirac_flag ); + Real_aux = RealBuffer[0][0][l] + RealBuffer[1][0][l]; + Imag_aux = ImagBuffer[0][0][l] + ImagBuffer[1][0][l]; + + reference_power[l] = Real_aux * Real_aux + Imag_aux * Imag_aux; + proto_power_smooth[l] += reference_power[l]; + p_proto_buffer[2 * l] = Real_aux; + p_proto_buffer[2 * l + 1] = Imag_aux; + + p_proto_buffer[2 * num_freq_bands + 2 * l] = RealBuffer[0][0][l] - RealBuffer[1][0][l]; + p_proto_buffer[2 * num_freq_bands + 2 * l + 1] = ImagBuffer[0][0][l] - ImagBuffer[1][0][l]; + proto_power_smooth[l + num_freq_bands] += p_proto_buffer[2 * num_freq_bands + 2 * l] * p_proto_buffer[2 * num_freq_bands + 2 * l] + p_proto_buffer[2 * num_freq_bands + 2 * l + 1] * p_proto_buffer[2 * num_freq_bands + 2 * l + 1]; + + proto_frame_f[2 * l] = Real_aux; + proto_frame_f[2 * l + 1] = Imag_aux; + + proto_frame_f[2 * num_freq_bands + 2 * l] = RealBuffer[0][0][l]; + proto_frame_f[2 * num_freq_bands + 2 * l + 1] = ImagBuffer[0][0][l]; + proto_frame_f[4 * num_freq_bands + 2 * l] = RealBuffer[1][0][l]; + proto_frame_f[4 * num_freq_bands + 2 * l + 1] = ImagBuffer[1][0][l]; } } - for ( slot_idx = 0; slot_idx < hSpatParamRendCom->subframe_nbslots[subframe_idx]; slot_idx++ ) + return; +} + + +static void protoSignalComputation4( + float RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], + float ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], + float *proto_frame_f, + float *proto_direct_buffer_f, + float *reference_power, + float *proto_power_smooth, + const int16_t slot_index, + const int16_t num_outputs_diff, + const int16_t num_freq_bands, + const float *mtx_hoa_decoder, + const int16_t nchan_transport, + const int16_t *sba_map_tc_ind ) +{ + int16_t k, l; + int16_t n; + float sq_tmp; + float *p_proto_buffer; + + set_zero( reference_power, num_freq_bands ); + for ( k = 0; k < 4; k++ ) { - index_slot = slot_idx_start + slot_idx; - if ( hDirAC->hConfig->dec_param_estim == TRUE ) + for ( l = 0; l < num_freq_bands; l++ ) { - md_idx = hSpatParamRendCom->render_to_md_map[index_slot]; - } - else - { - md_idx = hSpatParamRendCom->render_to_md_map[subframe_idx]; + sq_tmp = RealBuffer[k][0][l] * RealBuffer[k][0][l] + ImagBuffer[k][0][l] * ImagBuffer[k][0][l]; + reference_power[l] += 0.5f * sq_tmp; } + } - if ( st_ivas->ivas_format == SBA_FORMAT ) - { - for ( ch = 0; ch < nchan_transport; ch++ ) - { - mvr2r( pppQMfFrame_ts_re[ch][slot_idx], Cldfb_RealBuffer[ch][0], hSpatParamRendCom->num_freq_bands ); - mvr2r( pppQMfFrame_ts_im[ch][slot_idx], Cldfb_ImagBuffer[ch][0], hSpatParamRendCom->num_freq_bands ); - } - } - else + /*For decorrelated diffuseness*/ + for ( l = 0; l < num_outputs_diff; l++ ) + { + for ( k = 0; k < num_freq_bands; k++ ) { - /* CLDFB Analysis*/ - for ( ch = 0; ch < nchan_transport; ch++ ) + proto_frame_f[2 * l * num_freq_bands + 2 * k] = 0.f; + proto_frame_f[2 * l * num_freq_bands + 2 * k + 1] = 0.f; + for ( n = 0; n < nchan_transport; n++ ) { - cldfbAnalysis_ts( &( st_ivas->hTcBuffer->tc[hDirACRend->sba_map_tc[ch]][hSpatParamRendCom->num_freq_bands * index_slot] ), - Cldfb_RealBuffer[ch][0], - Cldfb_ImagBuffer[ch][0], - hSpatParamRendCom->num_freq_bands, - st_ivas->cldfbAnaDec[ch] ); + proto_frame_f[2 * l * num_freq_bands + 2 * k] += RealBuffer[n][0][k] * mtx_hoa_decoder[l * 16 + sba_map_tc_ind[n]]; + proto_frame_f[2 * l * num_freq_bands + 2 * k + 1] += ImagBuffer[n][0][k] * mtx_hoa_decoder[l * 16 + sba_map_tc_ind[n]]; } } + } - /* CNG in DirAC, extra CLDFB ana for CNA*/ - if ( st_ivas->nchan_transport == 1 && st_ivas->hSCE[0]->hCoreCoder[0] != NULL && st_ivas->hSCE[0]->hCoreCoder[0]->cna_dirac_flag && st_ivas->ivas_format != SBA_FORMAT ) + p_proto_buffer = proto_direct_buffer_f + slot_index * 2 * num_freq_bands * num_outputs_diff; + for ( k = 0; k < num_outputs_diff; k++ ) + { + for ( l = 0; l < num_freq_bands; l++ ) { - Decoder_State *st = st_ivas->hSCE[0]->hCoreCoder[0]; - - generate_masking_noise_dirac( st->hFdCngDec->hFdCngCom, - st_ivas->cldfbAnaDec[1], - st_ivas->hTcBuffer->tc[1], - Cldfb_RealBuffer[1][0], - Cldfb_ImagBuffer[1][0], - index_slot, - st->cna_dirac_flag && st->flag_cna, - ( st->core_brate == FRAME_NO_DATA || st->core_brate == SID_2k40 ) && st->cng_type == FD_CNG && st->cng_sba_flag ); + sq_tmp = proto_frame_f[k * 2 * num_freq_bands + 2 * l] * proto_frame_f[k * 2 * num_freq_bands + 2 * l] + proto_frame_f[k * 2 * num_freq_bands + 2 * l + 1] * proto_frame_f[k * 2 * num_freq_bands + 2 * l + 1]; + proto_power_smooth[l + k * num_freq_bands] += sq_tmp; + p_proto_buffer[k * 2 * num_freq_bands + 2 * l] = proto_frame_f[k * 2 * num_freq_bands + 2 * l]; + p_proto_buffer[k * 2 * num_freq_bands + 2 * l + 1] = proto_frame_f[k * 2 * num_freq_bands + 2 * l + 1]; } + } - /* LFE synthesis */ - if ( st_ivas->mc_mode == MC_MODE_MCMASA && !hDirACRend->hOutSetup.separateChannelEnabled && !( hDirACRend->hOutSetup.output_config == AUDIO_CONFIG_LS_CUSTOM && hDirACRend->hOutSetup.num_lfe == 0 ) ) - { - ivas_lfe_synth_with_cldfb( st_ivas->hMasa->hMasaLfeSynth, - Cldfb_RealBuffer, Cldfb_ImagBuffer, - Cldfb_RealBuffer[MAX_OUTPUT_CHANNELS - 1], Cldfb_ImagBuffer[MAX_OUTPUT_CHANNELS - 1], - slot_idx, - md_idx, - nchan_transport ); - } + return; +} - /*-----------------------------------------------------------------* - * protoype signal computation - *-----------------------------------------------------------------*/ - if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) +/*------------------------------------------------------------------------- + * ivas_dirac_dec_compute_diffuse_proto() + * + * Compute diffuse prototype buffer and smooth power, only for decorrelated bands + *------------------------------------------------------------------------*/ + +static void ivas_dirac_dec_compute_diffuse_proto( + DIRAC_DEC_HANDLE hDirAC, /* i/o: DirAC handle */ + const int16_t slot_idx /* i : slot index */ +) +{ + int16_t k, l; + int16_t num_freq_bands, num_freq_bands_diff; + float *p_diff_buffer, *p_diff_buffer_1; + float *p_proto_diff, *p_power_smooth, *proto_frame_dec_f; + DIRAC_OUTPUT_SYNTHESIS_PARAMS *h_dirac_output_synthesis_params; + DIRAC_OUTPUT_SYNTHESIS_STATE *h_dirac_output_synthesis_state; + int16_t m; + float *p_hoa_enc; + + proto_frame_dec_f = hDirAC->proto_frame_dec_f; + h_dirac_output_synthesis_params = &( hDirAC->h_output_synthesis_psd_params ); + h_dirac_output_synthesis_state = &( hDirAC->h_output_synthesis_psd_state ); + + num_freq_bands = hDirAC->num_freq_bands; + num_freq_bands_diff = h_dirac_output_synthesis_params->max_band_decorr; + + p_diff_buffer = h_dirac_output_synthesis_state->proto_diffuse_buffer_f + slot_idx * 2 * num_freq_bands_diff * hDirAC->hOutSetup.nchan_out_woLFE; + p_diff_buffer_1 = p_diff_buffer + 1; + p_power_smooth = h_dirac_output_synthesis_state->proto_power_diff_smooth; + + if ( hDirAC->synthesisConf != DIRAC_SYNTHESIS_PSD_SHD ) + { + for ( k = 0; k < hDirAC->hOutSetup.nchan_out_woLFE; k++ ) { - if ( st_ivas->hCombinedOrientationData && st_ivas->hCombinedOrientationData->enableCombinedOrientation[subframe_idx] && st_ivas->hCombinedOrientationData->shd_rot_max_order == 0 ) - { - protoSignalComputation_shd( Cldfb_RealBuffer, Cldfb_ImagBuffer, - hDirACRend->h_output_synthesis_psd_state.proto_direct_buffer_f, - hDirACRend->h_output_synthesis_psd_state.proto_diffuse_buffer_f, - reference_power, slot_idx, nchan_transport, - hDirACRend->num_outputs_diff, - hSpatParamRendCom->num_freq_bands, - p_Rmat ); - } - else + p_proto_diff = proto_frame_dec_f + k * 2 * num_freq_bands; + for ( l = 0; l < num_freq_bands_diff; l++ ) { - protoSignalComputation_shd( Cldfb_RealBuffer, Cldfb_ImagBuffer, - hDirACRend->h_output_synthesis_psd_state.proto_direct_buffer_f, - hDirACRend->h_output_synthesis_psd_state.proto_diffuse_buffer_f, - reference_power, slot_idx, nchan_transport, - hDirACRend->num_outputs_diff, - hSpatParamRendCom->num_freq_bands, - 0 ); + *p_diff_buffer = *( p_proto_diff++ ); + *p_diff_buffer_1 = *( p_proto_diff++ ); + *( p_power_smooth++ ) += ( *p_diff_buffer ) * ( *p_diff_buffer ) + ( *p_diff_buffer_1 ) * ( *p_diff_buffer_1 ); + p_diff_buffer += 2; + p_diff_buffer_1 += 2; } } - else if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_MONO ) - { - protoSignalComputation2( Cldfb_RealBuffer, Cldfb_ImagBuffer, hDirACRend->proto_frame_f, - hDirACRend->h_output_synthesis_psd_state.proto_direct_buffer_f, - reference_power, hDirACRend->h_output_synthesis_psd_state.proto_power_smooth, - 0, slot_idx, hSpatParamRendCom->num_freq_bands, hDirACRend->masa_stereo_type_detect ); - } - else + } + else + { + /*DIRAC_SYNTHESIS_PSD_SHD: Virtual LS->HOA encoding*/ + for ( k = 0; k < hDirAC->hOutSetup.nchan_out_woLFE; k++ ) { - switch ( nchan_transport ) + for ( l = 0; l < num_freq_bands_diff; l++ ) { - case 11: - case 8: - case 6: - case 4: - protoSignalComputation4( Cldfb_RealBuffer, Cldfb_ImagBuffer, - hDirACRend->proto_frame_f, - hDirACRend->h_output_synthesis_psd_state.proto_direct_buffer_f, - reference_power, - hDirACRend->h_output_synthesis_psd_state.proto_power_smooth, - slot_idx, hDirACRend->num_outputs_diff, - hSpatParamRendCom->num_freq_bands, - hDirACRend->hoa_decoder, - nchan_transport, - hDirACRend->sba_map_tc ); - break; - case 2: - protoSignalComputation2( Cldfb_RealBuffer, Cldfb_ImagBuffer, - hDirACRend->proto_frame_f, - hDirACRend->h_output_synthesis_psd_state.proto_direct_buffer_f, - reference_power, - hDirACRend->h_output_synthesis_psd_state.proto_power_smooth, - hDirACRend->hOutSetup.is_loudspeaker_setup, - slot_idx, - hSpatParamRendCom->num_freq_bands, - hDirACRend->masa_stereo_type_detect ); - break; - case 1: - protoSignalComputation1( Cldfb_RealBuffer, Cldfb_ImagBuffer, - hDirACRend->proto_frame_f, - hDirACRend->h_output_synthesis_psd_state.proto_direct_buffer_f, - reference_power, - hDirACRend->h_output_synthesis_psd_state.proto_power_smooth, - slot_idx, - hDirACRend->num_protos_diff, - hSpatParamRendCom->num_freq_bands ); - break; - default: - return; - } - } + p_hoa_enc = hDirAC->hoa_encoder + k; + p_proto_diff = proto_frame_dec_f + 2 * l; + *p_diff_buffer = 0.f; + *p_diff_buffer_1 = 0.f; - /*-----------------------------------------------------------------* - * Compute DirAC parameters at decoder side - *-----------------------------------------------------------------*/ + /*LS to HOA*/ + for ( m = 0; m < hDirAC->num_outputs_diff; m++ ) + { + *p_diff_buffer += ( *p_hoa_enc ) * ( *p_proto_diff ); + *p_diff_buffer_1 += ( *p_hoa_enc ) * ( *( p_proto_diff + 1 ) ); + p_hoa_enc += hDirAC->hOutSetup.nchan_out_woLFE; + p_proto_diff += 2 * num_freq_bands; + } - if ( hDirAC->hConfig->dec_param_estim == TRUE ) - { - mvs2s( &hSpatParamRendCom->azimuth[md_idx][hDirAC->hConfig->enc_param_start_band], &azimuth[hDirAC->hConfig->enc_param_start_band], hSpatParamRendCom->num_freq_bands - hDirAC->hConfig->enc_param_start_band ); - mvs2s( &hSpatParamRendCom->elevation[md_idx][hDirAC->hConfig->enc_param_start_band], &elevation[hDirAC->hConfig->enc_param_start_band], hSpatParamRendCom->num_freq_bands - hDirAC->hConfig->enc_param_start_band ); - if ( ( st_ivas->hDecoderConfig->Opt_Headrotation || st_ivas->hDecoderConfig->Opt_ExternalOrientation ) && st_ivas->hCombinedOrientationData->shd_rot_max_order == 0 ) - { - num_freq_bands = hDirAC->band_grouping[hDirAC->hConfig->enc_param_start_band]; - rotateAziEle_DirAC( azimuth, elevation, num_freq_bands, hSpatParamRendCom->num_freq_bands, p_Rmat ); + *( p_power_smooth++ ) += ( *p_diff_buffer ) * ( *p_diff_buffer ) + ( *p_diff_buffer_1 ) * ( *p_diff_buffer_1 ); + p_diff_buffer += 2; + p_diff_buffer_1 += 2; } + } + } - hDirACRend->index_buffer_intensity = ( hDirACRend->index_buffer_intensity % DIRAC_NO_COL_AVG_DIFF ) + 1; /* averaging_length = 32 */ + return; +} - index = hDirACRend->index_buffer_intensity; - num_freq_bands = hDirAC->band_grouping[hDirAC->hConfig->enc_param_start_band]; +/*------------------------------------------------------------------------- + * computeDirectionAngles() + * + *------------------------------------------------------------------------*/ - computeIntensityVector_dec( Cldfb_RealBuffer, - Cldfb_ImagBuffer, - num_freq_bands, - hDirACRend->buffer_intensity_real[0][index - 1], - hDirACRend->buffer_intensity_real[1][index - 1], - hDirACRend->buffer_intensity_real[2][index - 1] ); +static void computeDirectionAngles( + float *intensity_real_x, + float *intensity_real_y, + float *intensity_real_z, + const int16_t num_frequency_bands, + int16_t *azimuth, + int16_t *elevation ) +{ + int16_t k; + float intensityNorm; + float x, y, z, radius; - computeDirectionAngles( hDirACRend->buffer_intensity_real[0][index - 1], - hDirACRend->buffer_intensity_real[1][index - 1], - hDirACRend->buffer_intensity_real[2][index - 1], - num_freq_bands, - azimuth, - elevation ); + for ( k = 0; k < num_frequency_bands; ++k ) - mvr2r( reference_power, &( hDirACRend->buffer_energy[( index - 1 ) * num_freq_bands] ), num_freq_bands ); + { + intensityNorm = *( intensity_real_x ) * *( intensity_real_x ) + + *( intensity_real_y ) * *( intensity_real_y ) + + *( intensity_real_z ) * *( intensity_real_z ); - computeDiffuseness( hDirACRend->buffer_intensity_real, hDirACRend->buffer_energy, num_freq_bands, hSpatParamRendCom->diffuseness_vector[md_idx] ); + if ( intensityNorm <= EPSILON ) + { + intensityNorm = 1.0f; + x = 1.0f; + y = 0.0f; + z = 0.0f; + intensity_real_x++; + intensity_real_y++; + intensity_real_z++; } - -#ifdef DEBUG_MODE_DIRAC + else { - static FILE *fp_direction_vector = NULL, *fp_diffuseness = NULL, *fp_referencePower = NULL; + intensityNorm = sqrtf( 1.f / intensityNorm ); + x = *( intensity_real_x++ ) * intensityNorm; + y = *( intensity_real_y++ ) * intensityNorm; + z = *( intensity_real_z++ ) * intensityNorm; + } + radius = sqrtf( x * x + y * y ); + azimuth[k] = (int16_t) ( max( -180.0f, min( 180.0f, atan2f( y, x ) / EVS_PI * 180.0f ) ) + 0.5f ); + elevation[k] = (int16_t) ( max( -90.0f, min( 180.0f, atan2f( z, radius ) / EVS_PI * 180.0f ) ) + 0.5f ); + } + return; +} - if ( fp_direction_vector == NULL ) - fp_direction_vector = fopen( "./res/dbg_direction_vector_C_dec.bin", "wb" ); - if ( fp_diffuseness == NULL ) - fp_diffuseness = fopen( "./res/dbg_diffuseness_C_dec.bin", "wb" ); - if ( fp_referencePower == NULL ) - fp_referencePower = fopen( "./res/dbg_reference_power_C_dec.bin", "wb" ); +/*------------------------------------------------------------------------- + * ivas_masa_init_stereotype_detection() + * + * Initialize stereo transport signal type detection + *------------------------------------------------------------------------*/ - for ( i = 0; i < hSpatParamRendCom->num_freq_bands; i++ ) - { - float radius_length; - float dv[3]; +static void ivas_masa_init_stereotype_detection( + MASA_STEREO_TYPE_DETECT *stereo_type_detect ) +{ + stereo_type_detect->masa_stereo_type = MASA_STEREO_DOWNMIX; + stereo_type_detect->current_stereo_type = MASA_STEREO_DOWNMIX; + stereo_type_detect->type_change_direction = MASA_STEREO_DOWNMIX; - if ( hDirAC->hConfig->dec_param_estim == FALSE ) - { - radius_length = cos( hDirAC->elevation[subframe_idx][i] * PI_OVER_180 ); - dv[0] = radius_length * cos( hDirAC->azimuth[subframe_idx][i] * PI_OVER_180 ); - dv[1] = radius_length * sin( hDirAC->azimuth[subframe_idx][i] * PI_OVER_180 ); - dv[2] = sin( hDirAC->elevation[subframe_idx][i] * PI_OVER_180 ); + stereo_type_detect->counter = 0; + stereo_type_detect->interpolator = 0; - fwrite( dv, sizeof( float ), 3, fp_direction_vector ); - fwrite( &( hDirAC->diffuseness_vector[0][i] ), sizeof( float ), 1, fp_diffuseness ); - if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) - { - reference_power[i] = Cldfb_RealBuffer[0][0][i] * Cldfb_RealBuffer[0][0][i] + Cldfb_ImagBuffer[0][0][i] * Cldfb_ImagBuffer[0][0][i]; - } - fwrite( &( reference_power[i] ), sizeof( float ), 1, fp_referencePower ); - } - else - { - radius_length = cos( hDirAC->elevation[index_slot][i] * PI_OVER_180 ); - dv[0] = radius_length * cos( hDirAC->azimuth[index_slot][i] * PI_OVER_180 ); - dv[1] = radius_length * sin( hDirAC->azimuth[index_slot][i] * PI_OVER_180 ); - dv[2] = sin( hDirAC->elevation[index_slot][i] * PI_OVER_180 ); + stereo_type_detect->dipole_freq_range[0] = 1; + stereo_type_detect->dipole_freq_range[1] = 3; - fwrite( dv, sizeof( float ), 3, fp_direction_vector ); - fwrite( &( hDirAC->diffuseness_vector[index_slot][i] ), sizeof( float ), 1, fp_diffuseness ); - fwrite( &( reference_power[i] ), sizeof( float ), 1, fp_referencePower ); - } - } - } -#endif + stereo_type_detect->left_bb_power = 0.0f; /* Broadband estimates */ + stereo_type_detect->right_bb_power = 0.0f; + stereo_type_detect->total_bb_power = 0.0f; - /*-----------------------------------------------------------------* - * frequency domain decorrelation - *-----------------------------------------------------------------*/ + stereo_type_detect->left_hi_power = 0.0f; /* High-frequency estimates */ + stereo_type_detect->right_hi_power = 0.0f; + stereo_type_detect->total_hi_power = 0.0f; + + set_zero( stereo_type_detect->sum_power, MASA_SUM_FREQ_RANGE_BINS ); + set_zero( stereo_type_detect->total_power, MASA_SUM_FREQ_RANGE_BINS ); + + stereo_type_detect->subtract_power_y = 0.0f; + stereo_type_detect->subtract_power_y_smooth = 0.0f; + stereo_type_detect->target_power_y_smooth = 0.0f; + + stereo_type_detect->lr_total_bb_ratio_db = 0.0f; + stereo_type_detect->lr_total_hi_ratio_db = 0.0f; + stereo_type_detect->min_sum_total_ratio_db = 0.0f; + stereo_type_detect->subtract_target_ratio_db = 0.0f; + + return; +} + + +/*------------------------------------------------------------------------- + * ivas_masa_stereotype_detection() + * + * Detect the type of the transport audio signals + *------------------------------------------------------------------------*/ - if ( hDirACRend->proto_signal_decorr_on == 1 ) - { - /* decorrelate prototype frame */ - if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) - { - ivas_dirac_dec_decorr_process( hSpatParamRendCom->num_freq_bands, - hDirACRend->num_outputs_diff, - hDirACRend->num_protos_diff, - hDirACRend->synthesisConf, - nchan_transport, - hDirACRend->h_output_synthesis_psd_state.proto_diffuse_buffer_f + slot_idx * 2 * hSpatParamRendCom->num_freq_bands * hDirACRend->num_outputs_diff, - hDirACRend->num_protos_diff, - hDirACRend->proto_index_diff, - hDirACRend->h_output_synthesis_psd_state.proto_diffuse_buffer_f + slot_idx * 2 * hSpatParamRendCom->num_freq_bands * hDirACRend->num_outputs_diff + 2 * hSpatParamRendCom->num_freq_bands * min( 4, nchan_transport ), - onset_filter, - hDirACRend->h_freq_domain_decorr_ap_params, - hDirACRend->h_freq_domain_decorr_ap_state ); +static void ivas_masa_stereotype_detection( + MASA_STEREO_TYPE_DETECT *stereo_type_detect ) +{ + float lr_total_bb_ratio_db = stereo_type_detect->lr_total_bb_ratio_db; + float lr_total_hi_ratio_db = stereo_type_detect->lr_total_hi_ratio_db; + float min_sum_total_ratio_db = stereo_type_detect->min_sum_total_ratio_db; + float subtract_target_ratio_db = stereo_type_detect->subtract_target_ratio_db; + float change_to_spaced; + int16_t change_to_spaced_selection; + float change_to_downmix; + float change_to_downmix2; + int16_t change_to_downmix_selection; + float subtract_temp; + float min_sum_temp; + float lr_total_bb_temp; + float lr_total_hi_temp; + + /* Determine if the determined features match the spaced mic type */ + change_to_spaced_selection = 0; + if ( subtract_target_ratio_db < -3.0f ) + { + subtract_temp = ( -subtract_target_ratio_db - 3.0f ) / 3.0f; + min_sum_temp = max( -min_sum_total_ratio_db / 6.0f, 0.0f ); + lr_total_bb_temp = lr_total_bb_ratio_db / 6.0f; - v_multc( onset_filter, 0.25f, onset_filter, hSpatParamRendCom->num_freq_bands ); - v_add( onset_filter, onset_filter_subframe, onset_filter_subframe, hSpatParamRendCom->num_freq_bands ); - p_onset_filter = onset_filter_subframe; - } - else - { - ivas_dirac_dec_decorr_process( hSpatParamRendCom->num_freq_bands, - hDirACRend->num_outputs_diff, - hDirACRend->num_protos_diff, - hDirACRend->synthesisConf, - nchan_transport, - hDirACRend->proto_frame_f, - hDirACRend->num_protos_diff, - hDirACRend->proto_index_diff, - DirAC_mem.frame_dec_f, - onset_filter, - hDirACRend->h_freq_domain_decorr_ap_params, - hDirACRend->h_freq_domain_decorr_ap_state ); + change_to_spaced = subtract_temp + min_sum_temp + lr_total_bb_temp; - hDirACRend->proto_frame_dec_f = DirAC_mem.frame_dec_f; - p_onset_filter = onset_filter; - } - } - else + if ( change_to_spaced >= 1.0f ) { - if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) - { - set_f( onset_filter_subframe, 1.f, hSpatParamRendCom->num_freq_bands ); - p_onset_filter = onset_filter_subframe; - } - else - { - /* no frequency domain decorrelation: use prototype frame */ - hDirACRend->proto_frame_dec_f = hDirACRend->proto_frame_f; - p_onset_filter = NULL; - } + change_to_spaced_selection = 1; } + } - /*-----------------------------------------------------------------* - * output synthesis - *-----------------------------------------------------------------*/ + /* Determine if the determined features match the downmix type, according to a metric */ + change_to_downmix_selection = 0; + if ( subtract_target_ratio_db > 0.0f ) + { + subtract_temp = subtract_target_ratio_db / 3.0f; + min_sum_temp = ( min_sum_total_ratio_db + 1.0f ) / 6.0f; + lr_total_bb_temp = -lr_total_bb_ratio_db / 6.0f; + + change_to_downmix = subtract_temp + min_sum_temp + lr_total_bb_temp; - if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_PSD_LS || hDirACRend->synthesisConf == DIRAC_SYNTHESIS_PSD_SHD ) + if ( change_to_downmix >= 1.0f ) { - /*Compute diffuse prototypes*/ - ivas_dirac_dec_compute_diffuse_proto( hDirACRend, hSpatParamRendCom->num_freq_bands, slot_idx ); + change_to_downmix_selection = 1; } + } - /*Compute PSDs*/ - if ( st_ivas->hCombinedOrientationData && st_ivas->hCombinedOrientationData->enableCombinedOrientation[subframe_idx] && st_ivas->hCombinedOrientationData->shd_rot_max_order > 0 ) + /* Determine if the determined features match the downmix type, according to another metric */ + if ( lr_total_hi_ratio_db < -12.0f ) + { + subtract_temp = ( subtract_target_ratio_db + 4.0f ) / 3.0f; + min_sum_temp = min_sum_total_ratio_db / 6.0f; + lr_total_hi_temp = ( -lr_total_hi_ratio_db - 12.0f ) / 3.0f; + + change_to_downmix2 = subtract_temp + min_sum_temp + lr_total_hi_temp; + + if ( change_to_downmix2 >= 1.0f ) { - ivas_dirac_dec_output_synthesis_process_slot( reference_power, - p_onset_filter, - azimuth, - elevation, - hSpatParamRendCom->diffuseness_vector[md_idx], - hSpatParamRendCom, - hDirACRend, - st_ivas->hCombinedOrientationData->shd_rot_max_order, - p_Rmat, - st_ivas->hVBAPdata, - hDirACRend->hOutSetup, - nchan_transport, - md_idx, - hodirac_flag, - hDirAC->hConfig->dec_param_estim ); + change_to_downmix_selection = 1; } - else + } + + if ( stereo_type_detect->counter < 400 ) + { + stereo_type_detect->counter++; + } + else + { + if ( change_to_spaced_selection == 1 ) { - ivas_dirac_dec_output_synthesis_process_slot( reference_power, - p_onset_filter, - azimuth, - elevation, - hSpatParamRendCom->diffuseness_vector[md_idx], - hSpatParamRendCom, - hDirACRend, - 0, - 0, - st_ivas->hVBAPdata, - hDirACRend->hOutSetup, - nchan_transport, - md_idx, - hodirac_flag, - hDirAC->hConfig->dec_param_estim ); + stereo_type_detect->masa_stereo_type = MASA_STEREO_SPACED_MICS; } - - if ( hDirAC->hConfig->dec_param_estim ) + else if ( change_to_downmix_selection == 1 ) { - float fac = 1.0f / (float) hSpatParamRendCom->subframe_nbslots[subframe_idx]; - v_multc_acc( hSpatParamRendCom->diffuseness_vector[md_idx], fac, diffuseness_vector, hSpatParamRendCom->num_freq_bands ); + stereo_type_detect->masa_stereo_type = MASA_STEREO_DOWNMIX; } + } - if ( hDirACRend->synthesisConf != DIRAC_SYNTHESIS_GAIN_SHD ) + if ( stereo_type_detect->interpolator == 0 ) + { + if ( stereo_type_detect->current_stereo_type != stereo_type_detect->masa_stereo_type ) { - v_add( reference_power, reference_power_smooth, reference_power_smooth, hSpatParamRendCom->num_freq_bands ); + stereo_type_detect->interpolator = 1; + stereo_type_detect->type_change_direction = stereo_type_detect->masa_stereo_type; } } - ivas_dirac_dec_output_synthesis_get_interpolator( &hDirACRend->h_output_synthesis_psd_params, hSpatParamRendCom->subframe_nbslots[subframe_idx] ); + return; +} - if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) +/*------------------------------------------------------------------------- + * computeIntensityVector_dec() + * + * + *------------------------------------------------------------------------*/ + +static void computeIntensityVector_dec( + float Cldfb_RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], + float Cldfb_ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], + const int16_t num_frequency_bands, + float *intensity_real_x, + float *intensity_real_y, + float *intensity_real_z ) +{ + /* + * W = a + ib; Y = c + id + * real(W*Y') = ac + bd + */ + int16_t i; + float real, img; + + for ( i = 0; i < num_frequency_bands; ++i ) { - ivas_dirac_dec_output_synthesis_process_subframe_gain_shd( Cldfb_RealBuffer, - Cldfb_ImagBuffer, - hSpatParamRendCom, - hDirACRend, - nchan_transport, - hSpatParamRendCom->subframe_nbslots[subframe_idx], - p_onset_filter, - diffuseness_vector, - hodirac_flag, - hDirAC->hConfig->dec_param_estim ); + real = Cldfb_RealBuffer[0][0][i]; + img = Cldfb_ImagBuffer[0][0][i]; + intensity_real_x[i] = Cldfb_RealBuffer[3][0][i] * real + Cldfb_ImagBuffer[3][0][i] * img; + intensity_real_y[i] = Cldfb_RealBuffer[1][0][i] * real + Cldfb_ImagBuffer[1][0][i] * img; + intensity_real_z[i] = Cldfb_RealBuffer[2][0][i] * real + Cldfb_ImagBuffer[2][0][i] * img; } - else - { - /* Determine encoding quality based additional smoothing factor */ - float qualityBasedSmFactor = 1.0f; - if ( st_ivas->hMasa != NULL ) - { - qualityBasedSmFactor = st_ivas->hMasa->data.dir_decode_quality; - qualityBasedSmFactor *= qualityBasedSmFactor; - } + return; +} - ivas_dirac_dec_output_synthesis_process_subframe_psd_ls( Cldfb_RealBuffer, - Cldfb_ImagBuffer, - hSpatParamRendCom, - hDirACRend, - hSpatParamRendCom->subframe_nbslots[subframe_idx], - diffuseness_vector, - reference_power_smooth, - qualityBasedSmFactor, - hDirAC->hConfig->enc_param_start_band ); +/*------------------------------------------------------------------------- + * ivas_lfe_synth_with_cldfb() + * + * + *------------------------------------------------------------------------*/ + +static void ivas_lfe_synth_with_cldfb( + MCMASA_LFE_SYNTH_DATA_HANDLE hMasaLfeSynth, + float RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], + float ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], + float RealBufferLfe[MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], + float ImagBufferLfe[MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], + const int16_t slot_index, + const int16_t subframe_index, + const int16_t nchan_transport ) +{ + float lfeGain; + float transportGain; + float protoLfeReal, protoLfeImag; + int16_t i; + float transportEne, protoLfeEne, targetEneLfe, targetEneTrans; + + set_zero( RealBufferLfe[slot_index], CLDFB_NO_CHANNELS_MAX ); + set_zero( ImagBufferLfe[slot_index], CLDFB_NO_CHANNELS_MAX ); + + protoLfeReal = RealBuffer[0][0][0]; + protoLfeImag = ImagBuffer[0][0][0]; + transportEne = RealBuffer[0][0][0] * RealBuffer[0][0][0] + ImagBuffer[0][0][0] * ImagBuffer[0][0][0]; + for ( i = 1; i < nchan_transport; i++ ) + { + protoLfeReal += RealBuffer[i][0][0]; + protoLfeImag += ImagBuffer[i][0][0]; + transportEne += RealBuffer[i][0][0] * RealBuffer[i][0][0] + ImagBuffer[i][0][0] * ImagBuffer[i][0][0]; } + protoLfeEne = protoLfeReal * protoLfeReal + protoLfeImag * protoLfeImag; - /*-----------------------------------------------------------------* - * CLDFB synthesis (and binaural rendering) - *-----------------------------------------------------------------*/ + targetEneLfe = transportEne * hMasaLfeSynth->lfeToTotalEnergyRatio[subframe_index]; + targetEneTrans = transportEne * max( ( 1.0f - hMasaLfeSynth->lfeToTotalEnergyRatio[subframe_index] ), 0.01f ); - index_slot = slot_idx_start_cldfb_synth; + hMasaLfeSynth->transportEneSmooth *= MCMASA_LFE_SYNTH_ALPHA; + hMasaLfeSynth->protoLfeEneSmooth *= MCMASA_LFE_SYNTH_ALPHA; + hMasaLfeSynth->targetEneLfeSmooth *= MCMASA_LFE_SYNTH_ALPHA; + hMasaLfeSynth->targetEneTransSmooth *= MCMASA_LFE_SYNTH_ALPHA; - if ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) - { - /* Perform binaural rendering */ - ivas_binRenderer( st_ivas->hBinRenderer, -#ifdef SPLIT_REND_WITH_HEAD_ROT - &st_ivas->splitBinRend.splitrend.multiBinPoseData, -#endif - st_ivas->hCombinedOrientationData, - subframe_idx, - hSpatParamRendCom->subframe_nbslots[subframe_idx], - Cldfb_RealBuffer_Binaural, - Cldfb_ImagBuffer_Binaural, - Cldfb_RealBuffer, - Cldfb_ImagBuffer ); + hMasaLfeSynth->transportEneSmooth += transportEne; + hMasaLfeSynth->protoLfeEneSmooth += protoLfeEne; + hMasaLfeSynth->targetEneLfeSmooth += targetEneLfe; + hMasaLfeSynth->targetEneTransSmooth += targetEneTrans; -#ifdef SPLIT_REND_WITH_HEAD_ROT - if ( ( st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || - ( st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) - { - int16_t pos_idx; -#ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG - for ( pos_idx = 0; pos_idx < st_ivas->hBinRenderer->numPoses; pos_idx++ ) -#else - for ( pos_idx = 0; pos_idx < st_ivas->hBinRenderer->numPoses; pos_idx++ ) -#endif - { - for ( slot_idx = 0; slot_idx < hSpatParamRendCom->subframe_nbslots[subframe_idx]; slot_idx++ ) - { - for ( ch = 0; ch < st_ivas->hDecoderConfig->nchan_out; ch++ ) - { - mvr2r( Cldfb_RealBuffer_Binaural[pos_idx][ch][slot_idx], st_ivas->splitBinRend.hMultiBinCldfbData->Cldfb_RealBuffer_Binaural[( pos_idx * BINAURAL_CHANNELS ) + ch][slot_idx_start + slot_idx], hSpatParamRendCom->num_freq_bands ); - mvr2r( Cldfb_ImagBuffer_Binaural[pos_idx][ch][slot_idx], st_ivas->splitBinRend.hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural[( pos_idx * BINAURAL_CHANNELS ) + ch][slot_idx_start + slot_idx], hSpatParamRendCom->num_freq_bands ); - } - } - } - } -#endif - /* Inverse CLDFB*/ - for ( ch = 0; ch < st_ivas->hDecoderConfig->nchan_out; ch++ ) - { - /* open CLDFB buffer up to CLDFB_NO_CHANNELS_MAX bands for 48kHz */ - float *RealBuffer[MAX_PARAM_SPATIAL_SUBFRAMES]; - float *ImagBuffer[MAX_PARAM_SPATIAL_SUBFRAMES]; + lfeGain = min( 1.0f, sqrtf( hMasaLfeSynth->targetEneLfeSmooth / ( EPSILON + hMasaLfeSynth->protoLfeEneSmooth ) ) ); + transportGain = min( 1.0f, sqrtf( hMasaLfeSynth->targetEneTransSmooth / ( EPSILON + hMasaLfeSynth->transportEneSmooth ) ) ); - for ( i = 0; i < hSpatParamRendCom->subframe_nbslots[subframe_idx]; i++ ) - { -#ifdef SPLIT_REND_WITH_HEAD_ROT - RealBuffer[i] = Cldfb_RealBuffer_Binaural[0][ch][i]; - ImagBuffer[i] = Cldfb_ImagBuffer_Binaural[0][ch][i]; -#else - RealBuffer[i] = Cldfb_RealBuffer_Binaural[ch][i]; - ImagBuffer[i] = Cldfb_ImagBuffer_Binaural[ch][i]; -#endif - } + RealBufferLfe[slot_index][0] = protoLfeReal * lfeGain; + ImagBufferLfe[slot_index][0] = protoLfeImag * lfeGain; - cldfbSynthesis( RealBuffer, - ImagBuffer, - &( output_f[ch][index_slot * hSpatParamRendCom->num_freq_bands] ), - hSpatParamRendCom->num_freq_bands * hSpatParamRendCom->subframe_nbslots[subframe_idx], - st_ivas->cldfbSynDec[ch] ); - } - } - else if ( st_ivas->ivas_format == SBA_FORMAT ) + RealBuffer[0][0][0] *= transportGain; + ImagBuffer[0][0][0] *= transportGain; + for ( i = 1; i < nchan_transport; i++ ) { - for ( ch = 0; ch < hDirACRend->hOutSetup.nchan_out_woLFE; ch++ ) - { - for ( slot_idx = 0; slot_idx < hSpatParamRendCom->subframe_nbslots[subframe_idx]; slot_idx++ ) - { - mvr2r( Cldfb_RealBuffer[ch][slot_idx], pppQMfFrame_ts_re[ch][slot_idx], hSpatParamRendCom->num_freq_bands ); - mvr2r( Cldfb_ImagBuffer[ch][slot_idx], pppQMfFrame_ts_im[ch][slot_idx], hSpatParamRendCom->num_freq_bands ); - } - } + RealBuffer[i][0][0] *= transportGain; + ImagBuffer[i][0][0] *= transportGain; } - else - { - float *RealBuffer[MAX_PARAM_SPATIAL_SUBFRAMES]; - float *ImagBuffer[MAX_PARAM_SPATIAL_SUBFRAMES]; - int16_t outchannels; - idx_in = 0; - idx_lfe = 0; + return; +} - outchannels = hDirACRend->hOutSetup.nchan_out_woLFE + hDirACRend->hOutSetup.num_lfe; - if ( hDirACRend->hOutSetup.separateChannelEnabled && ( hDirACRend->hOutSetup.output_config == AUDIO_CONFIG_5_1 || - hDirACRend->hOutSetup.output_config == AUDIO_CONFIG_7_1 || - hDirACRend->hOutSetup.output_config == AUDIO_CONFIG_5_1_2 || - hDirACRend->hOutSetup.output_config == AUDIO_CONFIG_5_1_4 || - hDirACRend->hOutSetup.output_config == AUDIO_CONFIG_7_1_4 || - ( hDirACRend->hOutSetup.output_config == AUDIO_CONFIG_LS_CUSTOM && st_ivas->hLsSetupCustom->separate_ch_found ) ) ) - { - outchannels++; - } - if ( hDirACRend->hOutSetup.separateChannelEnabled && hDirACRend->hOutSetup.output_config == AUDIO_CONFIG_LS_CUSTOM ) - { - float tmp_separated[L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES]; - float tmp_lfe[L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES]; - const int16_t subframe_start_sample = index_slot * hSpatParamRendCom->num_freq_bands; - const int16_t num_samples_subframe = hSpatParamRendCom->num_freq_bands * hSpatParamRendCom->subframe_nbslots[subframe_idx]; +/*------------------------------------------------------------------------- + * rotateAziEle_DirAC() + * + * Apply rotation to DirAC DOAs + *------------------------------------------------------------------------*/ - /* Move the separated and the LFE channels to temporary variables as spatial synthesis may overwrite current channels */ - mvr2r( &( output_f[st_ivas->hOutSetup.separateChannelIndex][subframe_start_sample] ), tmp_separated, num_samples_subframe ); - mvr2r( &( output_f[LFE_CHANNEL][subframe_start_sample] ), tmp_lfe, num_samples_subframe ); +static void rotateAziEle_DirAC( + int16_t *azi, /* i/o: array of azimuth values */ + int16_t *ele, /* i/o: array of elevation values */ + const int16_t band1, /* i : bands to work on (lower limit) */ + const int16_t band2, /* i : bands to work on (upper bound) */ + const float *p_Rmat /* i : pointer to real-space rotation matrix */ +) +{ + int16_t b; + float dv_0, dv_1, dv_2; + float dv_r_0, dv_r_1, dv_r_2; + float w; - for ( ch = 0; ch < outchannels; ch++ ) - { - if ( ( hDirACRend->hOutSetup.num_lfe > 0 ) && ( hDirACRend->hOutSetup.index_lfe[idx_lfe] == ch ) ) - { - /* Move the LFE channel to the correct place */ - mvr2r( tmp_lfe, &( output_f[ch][subframe_start_sample] ), num_samples_subframe ); + push_wmops( "rotateAziEle_DirAC" ); - if ( idx_lfe < ( hDirACRend->hOutSetup.num_lfe - 1 ) ) - { - idx_lfe++; - } - } - else if ( ( st_ivas->hLsSetupCustom->separate_ch_found ) && ( hDirACRend->hOutSetup.separateChannelIndex == ch ) ) - { - /* Move the separated channel to the correct place. Thus, the separated channel is - * combined with the synthesized channels here when there is a matching channel. */ - mvr2r( tmp_separated, &( output_f[ch][subframe_start_sample] ), num_samples_subframe ); - } - else - { - /* open CLDFB buffer up to CLDFB_NO_CHANNELS_MAX bands for 48kHz */ - for ( i = 0; i < hSpatParamRendCom->subframe_nbslots[subframe_idx]; i++ ) - { - RealBuffer[i] = Cldfb_RealBuffer[idx_in][i]; - ImagBuffer[i] = Cldfb_ImagBuffer[idx_in][i]; - } - cldfbSynthesis( RealBuffer, ImagBuffer, &( output_f[ch][subframe_start_sample] ), num_samples_subframe, st_ivas->cldfbSynDec[idx_in] ); + for ( b = band1; b < band2; b++ ) + { - if ( !st_ivas->hLsSetupCustom->separate_ch_found ) - { - /* Pan the separated channel and mix with the synthesized channels. Thus, the separated channel - * is combined with the synthesized channels here when there is no matching channel. */ - v_multc_acc( tmp_separated, st_ivas->hLsSetupCustom->separate_ch_gains[idx_in], &( output_f[ch][subframe_start_sample] ), num_samples_subframe ); - } + /*Conversion spherical to cartesian coordinates*/ + w = cosf( ele[b] * PI_OVER_180 ); + dv_0 = w * cosf( azi[b] * PI_OVER_180 ); + dv_1 = w * sinf( azi[b] * PI_OVER_180 ); + dv_2 = sinf( ele[b] * PI_OVER_180 ); - idx_in++; - } - } - } - else - { - for ( ch = 0; ch < outchannels; ch++ ) - { - if ( ( hDirACRend->hOutSetup.num_lfe > 0 ) && ( hDirACRend->hOutSetup.index_lfe[idx_lfe] == ch ) ) - { - if ( st_ivas->mc_mode == MC_MODE_MCMASA && !hDirACRend->hOutSetup.separateChannelEnabled ) - { - for ( i = 0; i < hSpatParamRendCom->subframe_nbslots[subframe_idx]; i++ ) - { - RealBuffer[i] = Cldfb_RealBuffer[MAX_OUTPUT_CHANNELS - 1][i]; - ImagBuffer[i] = Cldfb_ImagBuffer[MAX_OUTPUT_CHANNELS - 1][i]; - } - cldfbSynthesis( RealBuffer, ImagBuffer, &( output_f[ch][index_slot * hSpatParamRendCom->num_freq_bands] ), hSpatParamRendCom->num_freq_bands * hSpatParamRendCom->subframe_nbslots[subframe_idx], st_ivas->cldfbSynDec[hDirACRend->hOutSetup.nchan_out_woLFE + idx_lfe] ); - } - else if ( st_ivas->mc_mode == MC_MODE_MCMASA && hDirACRend->hOutSetup.separateChannelEnabled ) - { - /* LFE has been synthesized in the time domain, do nothing. */ - } - else - { - set_zero( &( output_f[ch][index_slot * hSpatParamRendCom->num_freq_bands] ), hSpatParamRendCom->subframe_nbslots[subframe_idx] * hSpatParamRendCom->num_freq_bands ); - } + dv_r_0 = p_Rmat[0] * dv_0 + p_Rmat[1] * dv_1 + p_Rmat[2] * dv_2; + dv_r_1 = p_Rmat[3] * dv_0 + p_Rmat[4] * dv_1 + p_Rmat[5] * dv_2; + dv_r_2 = p_Rmat[6] * dv_0 + p_Rmat[7] * dv_1 + p_Rmat[8] * dv_2; - if ( idx_lfe < ( hDirACRend->hOutSetup.num_lfe - 1 ) ) - { - idx_lfe++; - } - } - else if ( ( hDirACRend->hOutSetup.separateChannelEnabled ) && ( hDirACRend->hOutSetup.separateChannelIndex == ch ) ) - { - /* The separated channel is already set to output_f[hOutSetup.separateChannelIndex]. Thus, the separated - * channel is combined with the synthesized channels here. */ - } - else - { - /* open CLDFB buffer up to CLDFB_NO_CHANNELS_MAX bands for 48kHz */ - for ( i = 0; i < hSpatParamRendCom->subframe_nbslots[subframe_idx]; i++ ) - { - RealBuffer[i] = Cldfb_RealBuffer[idx_in][i]; - ImagBuffer[i] = Cldfb_ImagBuffer[idx_in][i]; - } - cldfbSynthesis( RealBuffer, ImagBuffer, &( output_f[ch][index_slot * hSpatParamRendCom->num_freq_bands] ), hSpatParamRendCom->num_freq_bands * hSpatParamRendCom->subframe_nbslots[subframe_idx], st_ivas->cldfbSynDec[idx_in] ); - idx_in++; - } - } - } + /*Conversion spherical to cartesian coordinates*/ + azi[b] = (int16_t) ( atan2f( dv_r_1, dv_r_0 ) * _180_OVER_PI ); + ele[b] = (int16_t) ( atan2f( dv_r_2, sqrtf( dv_r_0 * dv_r_0 + dv_r_1 * dv_r_1 ) ) * _180_OVER_PI ); } - hSpatParamRendCom->slots_rendered += hSpatParamRendCom->subframe_nbslots[subframe_idx]; - hSpatParamRendCom->subframes_rendered++; pop_wmops(); diff --git a/lib_rend/ivas_dirac_decorr_dec.c b/lib_dec/ivas_dirac_decorr_dec.c similarity index 99% rename from lib_rend/ivas_dirac_decorr_dec.c rename to lib_dec/ivas_dirac_decorr_dec.c index e8311888819097d56c1a30837fe588d2cd501046..3687ed53b186321928374b7f55b33e8f6d99a998 100644 --- a/lib_rend/ivas_dirac_decorr_dec.c +++ b/lib_dec/ivas_dirac_decorr_dec.c @@ -37,9 +37,9 @@ #include "cnst.h" #include "prot.h" #include "ivas_prot.h" -#include "ivas_prot_rend.h" #include "ivas_stat_dec.h" #include "ivas_cnst.h" +#include "ivas_rom_com.h" #include "ivas_rom_dec.h" #ifdef DEBUGGING #include "debug.h" diff --git a/lib_rend/ivas_dirac_onsets_dec.c b/lib_dec/ivas_dirac_onsets_dec.c similarity index 99% rename from lib_rend/ivas_dirac_onsets_dec.c rename to lib_dec/ivas_dirac_onsets_dec.c index 8a03dc2c50da814c0788b1c81325e87633e0ec46..c094b45ff68aa32a7770f677b3c61e70b763f127 100644 --- a/lib_rend/ivas_dirac_onsets_dec.c +++ b/lib_dec/ivas_dirac_onsets_dec.c @@ -36,7 +36,6 @@ #include "cnst.h" #include "prot.h" #include "ivas_prot.h" -#include "ivas_prot_rend.h" #include "ivas_cnst.h" #include "ivas_rom_com.h" #include "ivas_rom_dec.h" diff --git a/lib_rend/ivas_dirac_output_synthesis_dec.c b/lib_dec/ivas_dirac_output_synthesis_dec.c similarity index 77% rename from lib_rend/ivas_dirac_output_synthesis_dec.c rename to lib_dec/ivas_dirac_output_synthesis_dec.c index 2788c7f0e17eed921e6e0bcc575dcc2bd36bd42f..68bd32528f3420e69a7361e3b56a75ddc77a792d 100644 --- a/lib_rend/ivas_dirac_output_synthesis_dec.c +++ b/lib_dec/ivas_dirac_output_synthesis_dec.c @@ -37,7 +37,6 @@ #include "cnst.h" #include "prot.h" #include "ivas_prot.h" -#include "ivas_prot_rend.h" #include "ivas_stat_dec.h" #include "ivas_cnst.h" #include "ivas_rom_com.h" @@ -88,12 +87,11 @@ static void normalizePanningGains( float *direct_response, const int16_t num_cha *------------------------------------------------------------------------*/ ivas_error ivas_dirac_dec_output_synthesis_open( - SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, /* i/o: common spatial renderer data handle */ - DIRAC_REND_HANDLE hDirACRend, /* i/o: DirAC renderer handle */ - RENDERER_TYPE renderer_type, /* i : renderer type */ - const int16_t nchan_transport, /* i : number of transport channels */ - const int32_t output_Fs, /* i : output sampling rate */ - const int16_t hodirac_flag /* i : flag to indicate HO-DirAC mode */ + DIRAC_DEC_HANDLE hDirAC, /* i/o: DirAC handle */ + RENDERER_TYPE renderer_type, /* i : renderer type */ + const int16_t nchan_transport, /* i : number of transport channels */ + const int32_t output_Fs, /* i : output sampling rate */ + const int16_t hodirac_flag /* i : flag to indicate HO-DirAC mode */ ) { int16_t idx, ch_idx; @@ -103,20 +101,20 @@ ivas_error ivas_dirac_dec_output_synthesis_open( float temp_alpha_synthesis[CLDFB_NO_CHANNELS_MAX]; /* pointers to structs for allocation */ - DIRAC_OUTPUT_SYNTHESIS_PARAMS *dirac_output_synthesis_params = &( hDirACRend->h_output_synthesis_psd_params ); - DIRAC_OUTPUT_SYNTHESIS_STATE *dirac_output_synthesis_state = &( hDirACRend->h_output_synthesis_psd_state ); + DIRAC_OUTPUT_SYNTHESIS_PARAMS *dirac_output_synthesis_params = &( hDirAC->h_output_synthesis_psd_params ); + DIRAC_OUTPUT_SYNTHESIS_STATE *dirac_output_synthesis_state = &( hDirAC->h_output_synthesis_psd_state ); /* check / set input parameters */ - assert( hSpatParamRendCom->num_freq_bands > 0 && "Error: Number of frequency bands <= 0!" ); - assert( hDirACRend->hOutSetup.nchan_out_woLFE > 0 && "Error: Number of output channels > 0!" ); - assert( hDirACRend->num_outputs_diff > 0 ); - assert( hSpatParamRendCom->slot_size > 0 ); - assert( hDirACRend->hOutSetup.is_loudspeaker_setup == 0 || hDirACRend->hOutSetup.is_loudspeaker_setup == 1 ); - assert( hDirACRend->diffuse_response_function != NULL ); + assert( hDirAC->num_freq_bands > 0 && "Error: Number of frequency bands <= 0!" ); + assert( hDirAC->hOutSetup.nchan_out_woLFE > 0 && "Error: Number of output channels > 0!" ); + assert( hDirAC->num_outputs_diff > 0 ); + assert( hDirAC->slot_size > 0 ); + assert( hDirAC->hOutSetup.is_loudspeaker_setup == 0 || hDirAC->hOutSetup.is_loudspeaker_setup == 1 ); + assert( hDirAC->diffuse_response_function != NULL ); - if ( hDirACRend->proto_signal_decorr_on ) + if ( hDirAC->proto_signal_decorr_on ) { - dirac_output_synthesis_params->max_band_decorr = hDirACRend->h_freq_domain_decorr_ap_params->max_band_decorr; + dirac_output_synthesis_params->max_band_decorr = hDirAC->h_freq_domain_decorr_ap_params->max_band_decorr; } else { @@ -128,16 +126,16 @@ ivas_error ivas_dirac_dec_output_synthesis_open( *-----------------------------------------------------------------*/ dirac_output_synthesis_state->diffuse_responses_square = NULL; - if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_MONO ) + if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_MONO ) { if ( ( dirac_output_synthesis_state->diffuse_responses_square = (float *) malloc( 2 * sizeof( float ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis\n" ) ); } } - else if ( hDirACRend->synthesisConf != DIRAC_SYNTHESIS_GAIN_SHD ) + else if ( hDirAC->synthesisConf != DIRAC_SYNTHESIS_GAIN_SHD ) { - if ( ( dirac_output_synthesis_state->diffuse_responses_square = (float *) malloc( hDirACRend->hOutSetup.nchan_out_woLFE * sizeof( float ) ) ) == NULL ) + if ( ( dirac_output_synthesis_state->diffuse_responses_square = (float *) malloc( hDirAC->hOutSetup.nchan_out_woLFE * sizeof( float ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis\n" ) ); } @@ -145,16 +143,16 @@ ivas_error ivas_dirac_dec_output_synthesis_open( /* prototype power buffers */ dirac_output_synthesis_state->proto_power_smooth_prev = NULL; - if ( hDirACRend->synthesisConf != DIRAC_SYNTHESIS_GAIN_SHD ) + if ( hDirAC->synthesisConf != DIRAC_SYNTHESIS_GAIN_SHD ) { - if ( ( dirac_output_synthesis_state->proto_power_smooth_prev = (float *) malloc( hSpatParamRendCom->num_freq_bands * hDirACRend->num_protos_dir * sizeof( float ) ) ) == NULL ) + if ( ( dirac_output_synthesis_state->proto_power_smooth_prev = (float *) malloc( hDirAC->num_freq_bands * hDirAC->num_protos_dir * sizeof( float ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis\n" ) ); } } - if ( dirac_output_synthesis_params->max_band_decorr > 0 && ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_PSD_LS || hDirACRend->synthesisConf == DIRAC_SYNTHESIS_PSD_SHD ) ) + if ( dirac_output_synthesis_params->max_band_decorr > 0 && ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_PSD_LS || hDirAC->synthesisConf == DIRAC_SYNTHESIS_PSD_SHD ) ) { - if ( ( dirac_output_synthesis_state->proto_power_diff_smooth_prev = (float *) malloc( dirac_output_synthesis_params->max_band_decorr * hDirACRend->hOutSetup.nchan_out_woLFE * sizeof( float ) ) ) == NULL ) + if ( ( dirac_output_synthesis_state->proto_power_diff_smooth_prev = (float *) malloc( dirac_output_synthesis_params->max_band_decorr * hDirAC->hOutSetup.nchan_out_woLFE * sizeof( float ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis\n" ) ); } @@ -173,42 +171,42 @@ ivas_error ivas_dirac_dec_output_synthesis_open( /* target PSD buffers */ if ( hodirac_flag ) { - size = hSpatParamRendCom->num_freq_bands * hDirACRend->num_outputs_dir * DIRAC_HO_NUMSECTORS; + size = hDirAC->num_freq_bands * hDirAC->num_outputs_dir * DIRAC_HO_NUMSECTORS; } else { - size = hSpatParamRendCom->num_freq_bands * hDirACRend->num_outputs_dir; + size = hDirAC->num_freq_bands * hDirAC->num_outputs_dir; } if ( ( dirac_output_synthesis_state->cy_cross_dir_smooth_prev = (float *) malloc( size * sizeof( float ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis\n" ) ); } - if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) + if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) { dirac_output_synthesis_state->cy_auto_dir_smooth_prev = NULL; - if ( ( dirac_output_synthesis_state->cy_auto_diff_smooth_prev = (float *) malloc( dirac_output_synthesis_params->max_band_decorr * hDirACRend->num_outputs_diff * sizeof( float ) ) ) == NULL ) + if ( ( dirac_output_synthesis_state->cy_auto_diff_smooth_prev = (float *) malloc( dirac_output_synthesis_params->max_band_decorr * hDirAC->num_outputs_diff * sizeof( float ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis\n" ) ); } } else { - if ( ( dirac_output_synthesis_state->cy_auto_dir_smooth_prev = (float *) malloc( hSpatParamRendCom->num_freq_bands * hDirACRend->num_outputs_dir * sizeof( float ) ) ) == NULL ) + if ( ( dirac_output_synthesis_state->cy_auto_dir_smooth_prev = (float *) malloc( hDirAC->num_freq_bands * hDirAC->num_outputs_dir * sizeof( float ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis\n" ) ); } - if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_PSD_SHD ) + if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_PSD_SHD ) { - if ( ( dirac_output_synthesis_state->cy_auto_diff_smooth_prev = (float *) malloc( hSpatParamRendCom->num_freq_bands * hDirACRend->num_outputs_dir * sizeof( float ) ) ) == NULL ) + if ( ( dirac_output_synthesis_state->cy_auto_diff_smooth_prev = (float *) malloc( hDirAC->num_freq_bands * hDirAC->num_outputs_dir * sizeof( float ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis\n" ) ); } } else { - if ( ( dirac_output_synthesis_state->cy_auto_diff_smooth_prev = (float *) malloc( hSpatParamRendCom->num_freq_bands * hDirACRend->num_outputs_diff * sizeof( float ) ) ) == NULL ) + if ( ( dirac_output_synthesis_state->cy_auto_diff_smooth_prev = (float *) malloc( hDirAC->num_freq_bands * hDirAC->num_outputs_diff * sizeof( float ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis\n" ) ); } @@ -221,23 +219,23 @@ ivas_error ivas_dirac_dec_output_synthesis_open( return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis\n" ) ); } - if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) + if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) { - if ( ( dirac_output_synthesis_state->gains_diff_prev = (float *) malloc( dirac_output_synthesis_params->max_band_decorr * hDirACRend->num_outputs_diff * sizeof( float ) ) ) == NULL ) + if ( ( dirac_output_synthesis_state->gains_diff_prev = (float *) malloc( dirac_output_synthesis_params->max_band_decorr * hDirAC->num_outputs_diff * sizeof( float ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis\n" ) ); } } - else if ( hDirACRend->synthesisConf != DIRAC_SYNTHESIS_PSD_SHD && hDirACRend->synthesisConf != DIRAC_SYNTHESIS_MONO ) + else if ( hDirAC->synthesisConf != DIRAC_SYNTHESIS_PSD_SHD && hDirAC->synthesisConf != DIRAC_SYNTHESIS_MONO ) { - if ( ( dirac_output_synthesis_state->gains_diff_prev = (float *) malloc( hSpatParamRendCom->num_freq_bands * hDirACRend->num_outputs_diff * sizeof( float ) ) ) == NULL ) + if ( ( dirac_output_synthesis_state->gains_diff_prev = (float *) malloc( hDirAC->num_freq_bands * hDirAC->num_outputs_diff * sizeof( float ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis\n" ) ); } } else { - if ( ( dirac_output_synthesis_state->gains_diff_prev = (float *) malloc( hSpatParamRendCom->num_freq_bands * hDirACRend->num_outputs_dir * sizeof( float ) ) ) == NULL ) + if ( ( dirac_output_synthesis_state->gains_diff_prev = (float *) malloc( hDirAC->num_freq_bands * hDirAC->num_outputs_dir * sizeof( float ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis\n" ) ); } @@ -248,32 +246,32 @@ ivas_error ivas_dirac_dec_output_synthesis_open( *-----------------------------------------------------------------*/ /* compute alpha */ - if ( !( renderer_type == RENDERER_BINAURAL_PARAMETRIC || renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || hDirACRend->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) ) + if ( !( renderer_type == RENDERER_BINAURAL_PARAMETRIC || renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || hDirAC->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) ) { - computeAlphaSynthesis( temp_alpha_synthesis, DIRAC_AVG_LENGTH_SYNTH_MS, DIRAC_ALPHA_MAX, &dirac_output_synthesis_params->numAlphas, hSpatParamRendCom->slot_size, hSpatParamRendCom->num_freq_bands, hDirACRend->frequency_axis, output_Fs ); + computeAlphaSynthesis( temp_alpha_synthesis, DIRAC_AVG_LENGTH_SYNTH_MS, DIRAC_ALPHA_MAX, &dirac_output_synthesis_params->numAlphas, hDirAC->slot_size, hDirAC->num_freq_bands, hDirAC->frequency_axis, output_Fs ); if ( ( dirac_output_synthesis_params->alpha_synthesis = (float *) malloc( dirac_output_synthesis_params->numAlphas * sizeof( float ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis\n" ) ); } mvr2r( temp_alpha_synthesis, dirac_output_synthesis_params->alpha_synthesis, dirac_output_synthesis_params->numAlphas ); - computeAlphaSynthesis( temp_alpha_synthesis, DIRAC_AVG_LENGTH_SYNTH_MS_FAST, DIRAC_ALPHA_MAX_FAST, &dirac_output_synthesis_params->numAlphasFast, hSpatParamRendCom->slot_size, hSpatParamRendCom->num_freq_bands, hDirACRend->frequency_axis, output_Fs ); + computeAlphaSynthesis( temp_alpha_synthesis, DIRAC_AVG_LENGTH_SYNTH_MS_FAST, DIRAC_ALPHA_MAX_FAST, &dirac_output_synthesis_params->numAlphasFast, hDirAC->slot_size, hDirAC->num_freq_bands, hDirAC->frequency_axis, output_Fs ); if ( ( dirac_output_synthesis_params->alpha_synthesis_fast = (float *) malloc( dirac_output_synthesis_params->numAlphasFast * sizeof( float ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis\n" ) ); } mvr2r( temp_alpha_synthesis, dirac_output_synthesis_params->alpha_synthesis_fast, dirac_output_synthesis_params->numAlphasFast ); - if ( ( dirac_output_synthesis_state->reference_power_smooth_prev = (float *) malloc( hSpatParamRendCom->num_freq_bands * sizeof( float ) ) ) == NULL ) + if ( ( dirac_output_synthesis_state->reference_power_smooth_prev = (float *) malloc( hDirAC->num_freq_bands * sizeof( float ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis\n" ) ); } - if ( ( dirac_output_synthesis_state->direction_smoothness_prev = (float *) malloc( hSpatParamRendCom->num_freq_bands * sizeof( float ) ) ) == NULL ) + if ( ( dirac_output_synthesis_state->direction_smoothness_prev = (float *) malloc( hDirAC->num_freq_bands * sizeof( float ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis\n" ) ); } - set_zero( dirac_output_synthesis_state->reference_power_smooth_prev, hSpatParamRendCom->num_freq_bands ); - set_zero( dirac_output_synthesis_state->direction_smoothness_prev, hSpatParamRendCom->num_freq_bands ); + set_zero( dirac_output_synthesis_state->reference_power_smooth_prev, hDirAC->num_freq_bands ); + set_zero( dirac_output_synthesis_state->direction_smoothness_prev, hDirAC->num_freq_bands ); } else { @@ -290,13 +288,13 @@ ivas_error ivas_dirac_dec_output_synthesis_open( } /* prepare diffuse response function */ - if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_MONO ) + if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_MONO ) { num_diffuse_responses = 2; } else { - num_diffuse_responses = hDirACRend->hOutSetup.nchan_out_woLFE; + num_diffuse_responses = hDirAC->hOutSetup.nchan_out_woLFE; } if ( dirac_output_synthesis_state->diffuse_responses_square != NULL ) @@ -304,34 +302,34 @@ ivas_error ivas_dirac_dec_output_synthesis_open( for ( ch_idx = 0; ch_idx < num_diffuse_responses; ++ch_idx ) { /*dirac_output_synthesis_state->diffuse_responses_square[ch_idx] = pow(dirac_output_synthesis_params->diffuse_response_function[ch_idx]/max_response, 2.0f);*/ - tmp = hDirACRend->diffuse_response_function[ch_idx]; + tmp = hDirAC->diffuse_response_function[ch_idx]; dirac_output_synthesis_state->diffuse_responses_square[ch_idx] = tmp * tmp; } } - if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) + if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) { int16_t diff_compensation_order; float diff_nrg_total, diff_nrg, diff_nrg_trans, diff_nrg_decorr; diff_compensation_order = nchan_transport >= 3 ? 3 : 2; /* compensate missing diffuseness modelling up order 2, except for HR*/ - diff_compensation_order = min( diff_compensation_order, hDirACRend->hOutSetup.ambisonics_order ); + diff_compensation_order = min( diff_compensation_order, hDirAC->hOutSetup.ambisonics_order ); diff_nrg_total = 0; diff_nrg_trans = 0; diff_nrg_decorr = 0; for ( ch_idx = 0; ch_idx < ( diff_compensation_order + 1 ) * ( diff_compensation_order + 1 ); ch_idx++ ) { - diff_nrg = hDirACRend->diffuse_response_function[ch_idx] * hDirACRend->diffuse_response_function[ch_idx]; + diff_nrg = hDirAC->diffuse_response_function[ch_idx] * hDirAC->diffuse_response_function[ch_idx]; diff_nrg_total += diff_nrg; /* is it a transport channel?*/ - if ( ch_idx == 0 || hDirACRend->proto_index_dir[ch_idx] != 0 ) + if ( ch_idx == 0 || hDirAC->proto_index_dir[ch_idx] != 0 ) { diff_nrg_trans += diff_nrg; } /* is it a decorrelated or transport channel?*/ - if ( ch_idx < hDirACRend->num_outputs_diff ) + if ( ch_idx < hDirAC->num_outputs_diff ) { diff_nrg_decorr += diff_nrg; } @@ -356,10 +354,9 @@ ivas_error ivas_dirac_dec_output_synthesis_open( *------------------------------------------------------------------------*/ void ivas_dirac_dec_output_synthesis_init( - SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, /* i/o: common spatial renderer data handle */ - DIRAC_REND_HANDLE hDirACRend, /* i/o: DirAC renderer handle */ - const int16_t nchan_out_woLFE, /* i : number of output audio channels without LFE */ - const int16_t hodirac_flag /* i : flag to indicate HO-DirAC mode */ + DIRAC_DEC_HANDLE hDirAC, /* i/o: DirAC handle */ + const int16_t nchan_out_woLFE, /* i : number of output audio channels without LFE */ + const int16_t hodirac_flag /* i : flag to indicate HO-DirAC mode */ ) { int16_t size; @@ -367,8 +364,8 @@ void ivas_dirac_dec_output_synthesis_init( DIRAC_OUTPUT_SYNTHESIS_PARAMS *h_dirac_output_synthesis_params; DIRAC_OUTPUT_SYNTHESIS_STATE *h_dirac_output_synthesis_state; - h_dirac_output_synthesis_params = &( hDirACRend->h_output_synthesis_psd_params ); - h_dirac_output_synthesis_state = &( hDirACRend->h_output_synthesis_psd_state ); + h_dirac_output_synthesis_params = &( hDirAC->h_output_synthesis_psd_params ); + h_dirac_output_synthesis_state = &( hDirAC->h_output_synthesis_psd_state ); /*-----------------------------------------------------------------* * init outputSynthesisPSD_Init @@ -377,45 +374,45 @@ void ivas_dirac_dec_output_synthesis_init( /* initialize buffers */ if ( h_dirac_output_synthesis_state->cy_auto_dir_smooth_prev != NULL ) { - set_zero( h_dirac_output_synthesis_state->cy_auto_dir_smooth_prev, hSpatParamRendCom->num_freq_bands * hDirACRend->num_outputs_dir ); + set_zero( h_dirac_output_synthesis_state->cy_auto_dir_smooth_prev, hDirAC->num_freq_bands * hDirAC->num_outputs_dir ); } if ( hodirac_flag ) { - size = hSpatParamRendCom->num_freq_bands * hDirACRend->num_outputs_dir * DIRAC_HO_NUMSECTORS; + size = hDirAC->num_freq_bands * hDirAC->num_outputs_dir * DIRAC_HO_NUMSECTORS; } else { - size = hSpatParamRendCom->num_freq_bands * hDirACRend->num_outputs_dir; + size = hDirAC->num_freq_bands * hDirAC->num_outputs_dir; } set_zero( h_dirac_output_synthesis_state->cy_cross_dir_smooth_prev, size ); - if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) + if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) { - set_zero( h_dirac_output_synthesis_state->cy_auto_diff_smooth_prev, h_dirac_output_synthesis_params->max_band_decorr * hDirACRend->num_outputs_diff ); + set_zero( h_dirac_output_synthesis_state->cy_auto_diff_smooth_prev, h_dirac_output_synthesis_params->max_band_decorr * hDirAC->num_outputs_diff ); } - else if ( hDirACRend->synthesisConf != DIRAC_SYNTHESIS_PSD_SHD ) + else if ( hDirAC->synthesisConf != DIRAC_SYNTHESIS_PSD_SHD ) { - set_zero( h_dirac_output_synthesis_state->cy_auto_diff_smooth_prev, hSpatParamRendCom->num_freq_bands * hDirACRend->num_outputs_diff ); + set_zero( h_dirac_output_synthesis_state->cy_auto_diff_smooth_prev, hDirAC->num_freq_bands * hDirAC->num_outputs_diff ); } else { - set_zero( h_dirac_output_synthesis_state->cy_auto_diff_smooth_prev, hSpatParamRendCom->num_freq_bands * hDirACRend->num_outputs_dir ); + set_zero( h_dirac_output_synthesis_state->cy_auto_diff_smooth_prev, hDirAC->num_freq_bands * hDirAC->num_outputs_dir ); } if ( h_dirac_output_synthesis_state->proto_power_smooth_prev != NULL ) { - set_zero( h_dirac_output_synthesis_state->proto_power_smooth_prev, hSpatParamRendCom->num_freq_bands * hDirACRend->num_protos_dir ); + set_zero( h_dirac_output_synthesis_state->proto_power_smooth_prev, hDirAC->num_freq_bands * hDirAC->num_protos_dir ); } set_zero( h_dirac_output_synthesis_state->gains_dir_prev, size ); - if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) + if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) { - set_zero( h_dirac_output_synthesis_state->gains_diff_prev, h_dirac_output_synthesis_params->max_band_decorr * hDirACRend->num_outputs_diff ); + set_zero( h_dirac_output_synthesis_state->gains_diff_prev, h_dirac_output_synthesis_params->max_band_decorr * hDirAC->num_outputs_diff ); } else { - set_zero( h_dirac_output_synthesis_state->gains_diff_prev, hSpatParamRendCom->num_freq_bands * hDirACRend->num_outputs_dir ); + set_zero( h_dirac_output_synthesis_state->gains_diff_prev, hDirAC->num_freq_bands * hDirAC->num_outputs_dir ); } if ( h_dirac_output_synthesis_state->proto_power_diff_smooth_prev != NULL ) @@ -434,12 +431,12 @@ void ivas_dirac_dec_output_synthesis_init( *------------------------------------------------------------------------*/ void ivas_dirac_dec_output_synthesis_close( - DIRAC_REND_HANDLE hDirACRend /* i/o: DirAC handle */ + DIRAC_DEC_HANDLE hDirAC /* i/o: DirAC handle */ ) { /* pointers to structs for allocation */ - DIRAC_OUTPUT_SYNTHESIS_PARAMS *dirac_output_synthesis_params = &( hDirACRend->h_output_synthesis_psd_params ); - DIRAC_OUTPUT_SYNTHESIS_STATE *dirac_output_synthesis_state = &( hDirACRend->h_output_synthesis_psd_state ); + DIRAC_OUTPUT_SYNTHESIS_PARAMS *dirac_output_synthesis_params = &( hDirAC->h_output_synthesis_psd_params ); + DIRAC_OUTPUT_SYNTHESIS_STATE *dirac_output_synthesis_state = &( hDirAC->h_output_synthesis_psd_state ); /*-----------------------------------------------------------------* * memory deallocation @@ -540,16 +537,15 @@ void ivas_dirac_dec_output_synthesis_process_slot( const int16_t *azimuth, const int16_t *elevation, const float *diffuseness, - SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, /* i/o: common spatial renderer data handle */ - DIRAC_REND_HANDLE hDirACRend, /* i/o: DirAC renderer handle */ + DIRAC_DEC_HANDLE hDirAC, /* i/o: DirAC handle */ const int16_t sh_rot_max_order, const float *p_Rmat, /* i : rotation matrix */ const VBAP_HANDLE hVBAPdata, /* i : VBAP structure */ const IVAS_OUTPUT_SETUP hOutSetup, /* i : output setup structure */ const int16_t nchan_transport, /* i : number of transport channels*/ const int16_t md_idx, - const int16_t hodirac_flag, /* i : flag to indicate HO-DirAC mode */ - const int16_t dec_param_estim ) + const int16_t hodirac_flag /* i : flag to indicate HO-DirAC mode */ +) { int16_t num_freq_bands, num_channels_dir; int16_t num_freq_bands_diff, num_channels_diff; @@ -559,8 +555,8 @@ void ivas_dirac_dec_output_synthesis_process_slot( DIRAC_OUTPUT_SYNTHESIS_PARAMS *h_dirac_output_synthesis_params; DIRAC_OUTPUT_SYNTHESIS_STATE *h_dirac_output_synthesis_state; - h_dirac_output_synthesis_params = &( hDirACRend->h_output_synthesis_psd_params ); - h_dirac_output_synthesis_state = &( hDirACRend->h_output_synthesis_psd_state ); + h_dirac_output_synthesis_params = &( hDirAC->h_output_synthesis_psd_params ); + h_dirac_output_synthesis_state = &( hDirAC->h_output_synthesis_psd_state ); h_dirac_output_synthesis_state->onset_filter = onset; @@ -569,22 +565,24 @@ void ivas_dirac_dec_output_synthesis_process_slot( *-----------------------------------------------------------------*/ /* collect some often used parameters */ - num_freq_bands = hSpatParamRendCom->num_freq_bands; - num_channels_dir = hDirACRend->num_outputs_dir; - num_channels_diff = hDirACRend->num_outputs_diff; + num_freq_bands = hDirAC->num_freq_bands; + num_channels_dir = hDirAC->num_outputs_dir; + num_channels_diff = hDirAC->num_outputs_diff; num_freq_bands_diff = h_dirac_output_synthesis_params->max_band_decorr; - if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_PSD_LS ) + if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_PSD_LS ) { num_channels_dir = hOutSetup.nchan_out_woLFE; } - if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD && hodirac_flag ) + if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD && hodirac_flag ) { - ivas_dirac_dec_compute_directional_responses( hSpatParamRendCom, - hDirACRend, + ivas_dirac_dec_compute_directional_responses( hDirAC, hVBAPdata, NULL, +#ifdef MASA_AND_OBJECTS + NULL, +#endif azimuth, elevation, md_idx, @@ -594,157 +592,157 @@ void ivas_dirac_dec_output_synthesis_process_slot( hodirac_flag ); } - if ( dec_param_estim == FALSE && hodirac_flag ) + if ( hDirAC->hConfig->dec_param_estim == FALSE && hodirac_flag ) { - if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) + if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) { - v_multc( hSpatParamRendCom->energy_ratio1[md_idx], -1.f, aux_buf, num_freq_bands ); + v_multc( hDirAC->energy_ratio1[md_idx], -1.f, aux_buf, num_freq_bands ); v_addc( aux_buf, 1.f, aux_buf, num_freq_bands ); - mvr2r( hSpatParamRendCom->energy_ratio1[md_idx], + mvr2r( hDirAC->energy_ratio1[md_idx], h_dirac_output_synthesis_state->direct_power_factor, num_freq_bands ); mvr2r( aux_buf, h_dirac_output_synthesis_state->diffuse_power_factor, num_freq_bands ); - v_multc( hSpatParamRendCom->energy_ratio2[md_idx], -1.f, aux_buf, num_freq_bands ); + v_multc( hDirAC->energy_ratio2[md_idx], -1.f, aux_buf, num_freq_bands ); v_addc( aux_buf, 1.f, aux_buf, num_freq_bands ); - mvr2r( hSpatParamRendCom->energy_ratio2[md_idx], - &h_dirac_output_synthesis_state->direct_power_factor[hSpatParamRendCom->num_freq_bands], + mvr2r( hDirAC->energy_ratio2[md_idx], + &h_dirac_output_synthesis_state->direct_power_factor[hDirAC->num_freq_bands], num_freq_bands ); mvr2r( aux_buf, - &h_dirac_output_synthesis_state->diffuse_power_factor[hSpatParamRendCom->num_freq_bands], + &h_dirac_output_synthesis_state->diffuse_power_factor[hDirAC->num_freq_bands], num_freq_bands ); } else { ivas_dirac_dec_compute_gain_factors( num_freq_bands, - hSpatParamRendCom->diffuseness_vector[md_idx], + hDirAC->diffuseness_vector[md_idx], h_dirac_output_synthesis_params->max_band_decorr, h_dirac_output_synthesis_state->direct_power_factor, h_dirac_output_synthesis_state->diffuse_power_factor ); } } - else // ( dec_param_estim == TRUE ) - if ( dec_param_estim == TRUE ) - { - - /* compute direct responses */ - ivas_dirac_dec_compute_directional_responses( hSpatParamRendCom, - hDirACRend, - hVBAPdata, - NULL, - azimuth, - elevation, - md_idx, - NULL, - sh_rot_max_order, - p_Rmat, - hodirac_flag ); + else if ( hDirAC->hConfig->dec_param_estim == TRUE ) + { + /* compute direct responses */ + ivas_dirac_dec_compute_directional_responses( hDirAC, + hVBAPdata, + NULL, +#ifdef MASA_AND_OBJECTS + NULL, +#endif + azimuth, + elevation, + md_idx, + NULL, + sh_rot_max_order, + p_Rmat, + hodirac_flag ); - if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) - { - ivas_dirac_dec_compute_gain_factors( num_freq_bands, - diffuseness, - h_dirac_output_synthesis_params->max_band_decorr, - h_dirac_output_synthesis_state->direct_power_factor, - h_dirac_output_synthesis_state->diffuse_power_factor ); + if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) + { + ivas_dirac_dec_compute_gain_factors( num_freq_bands, + diffuseness, + h_dirac_output_synthesis_params->max_band_decorr, + h_dirac_output_synthesis_state->direct_power_factor, + h_dirac_output_synthesis_state->diffuse_power_factor ); - v_multc( h_dirac_output_synthesis_state->direct_power_factor, - 0.25f, - h_dirac_output_synthesis_state->direct_power_factor, - num_freq_bands ); - v_multc( h_dirac_output_synthesis_state->diffuse_power_factor, - 0.25f, - h_dirac_output_synthesis_state->diffuse_power_factor, - num_freq_bands ); + v_multc( h_dirac_output_synthesis_state->direct_power_factor, + 0.25f, + h_dirac_output_synthesis_state->direct_power_factor, + num_freq_bands ); + v_multc( h_dirac_output_synthesis_state->diffuse_power_factor, + 0.25f, + h_dirac_output_synthesis_state->diffuse_power_factor, + num_freq_bands ); - /*Direct gain*/ - for ( ch_idx = 0; ch_idx < min( 4, nchan_transport ); ch_idx++ ) + /*Direct gain*/ + for ( ch_idx = 0; ch_idx < min( 4, nchan_transport ); ch_idx++ ) + { + int16_t k; + if ( ch_idx != 0 ) { - int16_t k; - if ( ch_idx != 0 ) - { - float a, b, c; + float a, b, c; - /*Directonal sound gain nrg compensation*/ - for ( k = 0; k < num_freq_bands_diff; k++ ) - { - a = h_dirac_output_synthesis_state->direct_responses[ch_idx * num_freq_bands + k]; - b = reference_power[k + num_freq_bands] / ( reference_power[k + ( ch_idx + 1 ) * num_freq_bands] + EPSILON ); - c = 1.f + ( 1.f / 6.f ) * ( h_dirac_output_synthesis_params->diffuse_compensation_factor_decorr - 1.f ); /*Diffuseness modellling nrg compensation*/ - h_dirac_output_synthesis_state->cy_cross_dir_smooth[ch_idx * num_freq_bands + k] += 0.25f * sqrtf( diffuseness[k] * c + ( ( 1.f - diffuseness[k] ) * a * a * b ) ); - } - for ( ; k < num_freq_bands; k++ ) - { - a = h_dirac_output_synthesis_state->direct_responses[ch_idx * num_freq_bands + k]; - b = reference_power[k + num_freq_bands] / ( reference_power[k + ( ch_idx + 1 ) * num_freq_bands] + EPSILON ); - c = 1.f + ( 1.f / 6.f ) * ( h_dirac_output_synthesis_params->diffuse_compensation_factor - 1.f ); /*Diffuseness modellling nrg compensation*/ - h_dirac_output_synthesis_state->cy_cross_dir_smooth[ch_idx * num_freq_bands + k] += 0.25f * sqrtf( diffuseness[k] * c + ( ( 1.f - diffuseness[k] ) * a * a * b ) ); - } + /*Directonal sound gain nrg compensation*/ + for ( k = 0; k < num_freq_bands_diff; k++ ) + { + a = h_dirac_output_synthesis_state->direct_responses[ch_idx * num_freq_bands + k]; + b = reference_power[k + num_freq_bands] / ( reference_power[k + ( ch_idx + 1 ) * num_freq_bands] + EPSILON ); + c = 1.f + ( 1.f / 6.f ) * ( h_dirac_output_synthesis_params->diffuse_compensation_factor_decorr - 1.f ); /*Diffuseness modellling nrg compensation*/ + h_dirac_output_synthesis_state->cy_cross_dir_smooth[ch_idx * num_freq_bands + k] += 0.25f * sqrtf( diffuseness[k] * c + ( ( 1.f - diffuseness[k] ) * a * a * b ) ); } - else + for ( ; k < num_freq_bands; k++ ) { - /*Diffuseness modellling nrg compensation*/ - for ( k = 0; k < num_freq_bands_diff; k++ ) - { - h_dirac_output_synthesis_state->cy_cross_dir_smooth[ch_idx * num_freq_bands + k] += 0.25f * sqrtf( 1.0f + diffuseness[k] * 0.5f * ( h_dirac_output_synthesis_params->diffuse_compensation_factor_decorr - 1.f ) ); - } - for ( ; k < num_freq_bands; k++ ) - { - h_dirac_output_synthesis_state->cy_cross_dir_smooth[ch_idx * num_freq_bands + k] += 0.25f * sqrtf( 1.0f + diffuseness[k] * 0.5f * ( h_dirac_output_synthesis_params->diffuse_compensation_factor - 1.f ) ); - } + a = h_dirac_output_synthesis_state->direct_responses[ch_idx * num_freq_bands + k]; + b = reference_power[k + num_freq_bands] / ( reference_power[k + ( ch_idx + 1 ) * num_freq_bands] + EPSILON ); + c = 1.f + ( 1.f / 6.f ) * ( h_dirac_output_synthesis_params->diffuse_compensation_factor - 1.f ); /*Diffuseness modellling nrg compensation*/ + h_dirac_output_synthesis_state->cy_cross_dir_smooth[ch_idx * num_freq_bands + k] += 0.25f * sqrtf( diffuseness[k] * c + ( ( 1.f - diffuseness[k] ) * a * a * b ) ); } } - - /*Directional gain (panning)*/ - for ( ch_idx = min( 4, nchan_transport ); ch_idx < num_channels_dir; ch_idx++ ) - { - v_mult( h_dirac_output_synthesis_state->direct_power_factor, - &h_dirac_output_synthesis_state->direct_responses[ch_idx * num_freq_bands], - aux_buf, - num_freq_bands ); - - v_add( aux_buf, - &h_dirac_output_synthesis_state->cy_cross_dir_smooth[ch_idx * num_freq_bands], - &h_dirac_output_synthesis_state->cy_cross_dir_smooth[ch_idx * num_freq_bands], - num_freq_bands ); - } - - /*Diffuse gain*/ - for ( ch_idx = min( 4, nchan_transport ); ch_idx < num_channels_diff; ch_idx++ ) + else { - v_multc( h_dirac_output_synthesis_state->diffuse_power_factor, - hDirACRend->diffuse_response_function[ch_idx], - aux_buf, - num_freq_bands_diff ); - - v_add( aux_buf, - &h_dirac_output_synthesis_state->cy_auto_diff_smooth[ch_idx * num_freq_bands_diff], - &h_dirac_output_synthesis_state->cy_auto_diff_smooth[ch_idx * num_freq_bands_diff], - num_freq_bands_diff ); + /*Diffuseness modellling nrg compensation*/ + for ( k = 0; k < num_freq_bands_diff; k++ ) + { + h_dirac_output_synthesis_state->cy_cross_dir_smooth[ch_idx * num_freq_bands + k] += 0.25f * sqrtf( 1.0f + diffuseness[k] * 0.5f * ( h_dirac_output_synthesis_params->diffuse_compensation_factor_decorr - 1.f ) ); + } + for ( ; k < num_freq_bands; k++ ) + { + h_dirac_output_synthesis_state->cy_cross_dir_smooth[ch_idx * num_freq_bands + k] += 0.25f * sqrtf( 1.0f + diffuseness[k] * 0.5f * ( h_dirac_output_synthesis_params->diffuse_compensation_factor - 1.f ) ); + } } + } - return; + /*Directional gain (panning)*/ + for ( ch_idx = min( 4, nchan_transport ); ch_idx < num_channels_dir; ch_idx++ ) + { + v_mult( h_dirac_output_synthesis_state->direct_power_factor, + &h_dirac_output_synthesis_state->direct_responses[ch_idx * num_freq_bands], + aux_buf, + num_freq_bands ); + + v_add( aux_buf, + &h_dirac_output_synthesis_state->cy_cross_dir_smooth[ch_idx * num_freq_bands], + &h_dirac_output_synthesis_state->cy_cross_dir_smooth[ch_idx * num_freq_bands], + num_freq_bands ); } - else + + /*Diffuse gain*/ + for ( ch_idx = min( 4, nchan_transport ); ch_idx < num_channels_diff; ch_idx++ ) { - /* compute reference and diffuse power factor for this frame */ - ivas_dirac_dec_compute_power_factors( num_freq_bands, - diffuseness, - h_dirac_output_synthesis_params->max_band_decorr, - h_dirac_output_synthesis_state->direct_power_factor, - h_dirac_output_synthesis_state->diffuse_power_factor ); + v_multc( h_dirac_output_synthesis_state->diffuse_power_factor, + hDirAC->diffuse_response_function[ch_idx], + aux_buf, + num_freq_bands_diff ); + + v_add( aux_buf, + &h_dirac_output_synthesis_state->cy_auto_diff_smooth[ch_idx * num_freq_bands_diff], + &h_dirac_output_synthesis_state->cy_auto_diff_smooth[ch_idx * num_freq_bands_diff], + num_freq_bands_diff ); } + + return; } + else + { + /* compute reference and diffuse power factor for this frame */ + ivas_dirac_dec_compute_power_factors( num_freq_bands, + diffuseness, + h_dirac_output_synthesis_params->max_band_decorr, + h_dirac_output_synthesis_state->direct_power_factor, + h_dirac_output_synthesis_state->diffuse_power_factor ); + } + } diff_start_band = 0; if ( h_dirac_output_synthesis_params->use_onset_filters ) { computeTargetPSDs_diffuse_with_onsets( num_channels_dir, num_freq_bands, h_dirac_output_synthesis_params->max_band_decorr, - hDirACRend->proto_index_diff, + hDirAC->proto_index_diff, h_dirac_output_synthesis_state->diffuse_power_factor, reference_power, h_dirac_output_synthesis_state->diffuse_responses_square, @@ -755,7 +753,7 @@ void ivas_dirac_dec_output_synthesis_process_slot( } /* process other PSDs only slot wise for 4 transport channels */ - if ( dec_param_estim == TRUE ) + if ( hDirAC->hConfig->dec_param_estim == TRUE ) { computeTargetPSDs_direct( num_channels_dir, num_freq_bands, h_dirac_output_synthesis_state->direct_power_factor, reference_power, h_dirac_output_synthesis_state->direct_responses, h_dirac_output_synthesis_state->direct_responses_square, h_dirac_output_synthesis_state->cy_auto_dir_smooth, h_dirac_output_synthesis_state->cy_cross_dir_smooth ); @@ -775,14 +773,13 @@ void ivas_dirac_dec_output_synthesis_process_slot( void ivas_dirac_dec_output_synthesis_process_subframe_gain_shd( float RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i : LS signals */ float ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i : LS signals */ - SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, /* i/o: common spatial renderer data handle */ - DIRAC_REND_HANDLE hDirACRend, /* i/o: DirAC renderer handle */ + DIRAC_DEC_HANDLE hDirAC, /* i/o: DirAC handle */ const int16_t nchan_transport, /* i : number of transport channels */ const int16_t nbslots, /* i : number of slots to process */ const float *onset_filter, float *diffuseness, - const int16_t hodirac_flag, /* i : flag to indicate HO-DirAC mode */ - const int16_t dec_param_estim ) + const int16_t hodirac_flag /* i : flag to indicate HO-DirAC mode */ +) { int16_t buf_idx, ch_idx, i, l; int16_t num_freq_bands, num_freq_bands_diff; @@ -805,15 +802,15 @@ void ivas_dirac_dec_output_synthesis_process_subframe_gain_shd( float ratio[DIRAC_HO_NUMSECTORS * CLDFB_NO_CHANNELS_MAX]; /* collect some often used parameters */ - h_dirac_output_synthesis_params = hDirACRend->h_output_synthesis_psd_params; - h_dirac_output_synthesis_state = hDirACRend->h_output_synthesis_psd_state; - proto_direct_index = hDirACRend->proto_index_dir; + h_dirac_output_synthesis_params = hDirAC->h_output_synthesis_psd_params; + h_dirac_output_synthesis_state = hDirAC->h_output_synthesis_psd_state; + proto_direct_index = hDirAC->proto_index_dir; - num_protos_dir = hDirACRend->num_protos_dir; - num_freq_bands = hSpatParamRendCom->num_freq_bands; + num_protos_dir = hDirAC->num_protos_dir; + num_freq_bands = hDirAC->num_freq_bands; num_freq_bands_diff = h_dirac_output_synthesis_params.max_band_decorr; - num_channels_dir = hDirACRend->num_outputs_dir; - num_channels_diff = hDirACRend->num_outputs_diff; + num_channels_dir = hDirAC->num_outputs_dir; + num_channels_diff = hDirAC->num_outputs_diff; nchan_transport_foa = min( 4, nchan_transport ); @@ -823,6 +820,7 @@ void ivas_dirac_dec_output_synthesis_process_subframe_gain_shd( if ( hodirac_flag ) { + assert( hDirAC->hConfig->dec_param_estim == FALSE ); /*Direct gain*/ for ( ch_idx = 0; ch_idx < nchan_transport_foa; ch_idx++ ) { @@ -847,7 +845,7 @@ void ivas_dirac_dec_output_synthesis_process_subframe_gain_shd( for ( l = 0; l < num_freq_bands; l++ ) { aux_buf[l] = 1.f - diffuseness[l]; - ratio[l] = 1.f - h_dirac_output_synthesis_state.direct_power_factor[hSpatParamRendCom->num_freq_bands + l]; + ratio[l] = 1.f - h_dirac_output_synthesis_state.direct_power_factor[hDirAC->num_freq_bands + l]; ratio[l + num_freq_bands] = 1.f - ratio[l]; } @@ -868,12 +866,12 @@ void ivas_dirac_dec_output_synthesis_process_subframe_gain_shd( for ( ch_idx = nchan_transport_foa; ch_idx < num_channels_diff; ch_idx++ ) { v_multc( h_dirac_output_synthesis_state.diffuse_power_factor, - hDirACRend->diffuse_response_function[ch_idx], + hDirAC->diffuse_response_function[ch_idx], &h_dirac_output_synthesis_state.cy_auto_diff_smooth[ch_idx * num_freq_bands_diff], num_freq_bands_diff ); } } - else if ( dec_param_estim == FALSE ) + else if ( hDirAC->hConfig->dec_param_estim == FALSE ) { /*Direct gain*/ for ( ch_idx = 0; ch_idx < nchan_transport_foa; ch_idx++ ) @@ -908,7 +906,7 @@ void ivas_dirac_dec_output_synthesis_process_subframe_gain_shd( /*Diffuse gain*/ for ( ch_idx = nchan_transport_foa; ch_idx < num_channels_diff; ch_idx++ ) { - v_multc( h_dirac_output_synthesis_state.diffuse_power_factor, hDirACRend->diffuse_response_function[ch_idx], &h_dirac_output_synthesis_state.cy_auto_diff_smooth[ch_idx * num_freq_bands_diff], num_freq_bands_diff ); + v_multc( h_dirac_output_synthesis_state.diffuse_power_factor, hDirAC->diffuse_response_function[ch_idx], &h_dirac_output_synthesis_state.cy_auto_diff_smooth[ch_idx * num_freq_bands_diff], num_freq_bands_diff ); } } @@ -1122,8 +1120,8 @@ void ivas_dirac_dec_output_synthesis_process_subframe_gain_shd( for ( l = 0; l < num_freq_bands_diff; l++ ) { g = g1 * ( *( p_gains_diff++ ) ) + g2 * ( *( p_gains_diff_prev++ ) ); - output_real[l * num_channels_dir + hDirACRend->sba_map_tc[ch_idx]] += g * ( *( p_proto++ ) ); /* maps ch_idx 5 to 8 */ - output_imag[l * num_channels_dir + hDirACRend->sba_map_tc[ch_idx]] += g * ( *( p_proto++ ) ); + output_real[l * num_channels_dir + hDirAC->sba_map_tc[ch_idx]] += g * ( *( p_proto++ ) ); /* maps ch_idx 5 to 8 */ + output_imag[l * num_channels_dir + hDirAC->sba_map_tc[ch_idx]] += g * ( *( p_proto++ ) ); } } else @@ -1140,14 +1138,14 @@ void ivas_dirac_dec_output_synthesis_process_subframe_gain_shd( * Copy output or HOA decoder *-----------------------------------------------------------------*/ - if ( hDirACRend->hOutSetup.is_loudspeaker_setup && hDirACRend->hoa_decoder != NULL ) + if ( hDirAC->hOutSetup.is_loudspeaker_setup && hDirAC->hoa_decoder != NULL ) { float *p_real, *p_imag; const float *hoa_decoder; - hoa_decoder = hDirACRend->hoa_decoder; + hoa_decoder = hDirAC->hoa_decoder; - for ( ch_idx = 0; ch_idx < hDirACRend->hOutSetup.nchan_out_woLFE; ch_idx++ ) + for ( ch_idx = 0; ch_idx < hDirAC->hOutSetup.nchan_out_woLFE; ch_idx++ ) { p_real = RealBuffer[ch_idx][buf_idx]; p_imag = ImagBuffer[ch_idx][buf_idx]; @@ -1221,13 +1219,11 @@ void ivas_dirac_dec_output_synthesis_process_subframe_gain_shd( void ivas_dirac_dec_output_synthesis_process_subframe_psd_ls( float RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i : LS signals */ float ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i : LS signals */ - SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, /* i/o: common spatial renderer data handle */ - DIRAC_REND_HANDLE hDirACRend, /* i/o: DirAC renderer handle */ + DIRAC_DEC_HANDLE hDirAC, /* i/o: DirAC handle */ const int16_t nbslots, /* i : number of slots to process */ float *diffuseness_vector, float *reference_power_smooth, - float qualityBasedSmFactor, - const int16_t enc_param_start_band ) + float qualityBasedSmFactor ) { int16_t buf_idx, num_freq_bands; int16_t diff_start_band; @@ -1260,24 +1256,24 @@ void ivas_dirac_dec_output_synthesis_process_subframe_psd_ls( push_wmops( "dirac_out_synth_sfr" ); - h_dirac_output_synthesis_params = &( hDirACRend->h_output_synthesis_psd_params ); - h_dirac_output_synthesis_state = &( hDirACRend->h_output_synthesis_psd_state ); - proto_direct_index = hDirACRend->proto_index_dir; - num_protos_dir = hDirACRend->num_protos_dir; - nchan_out_woLFE = hDirACRend->hOutSetup.nchan_out_woLFE; + h_dirac_output_synthesis_params = &( hDirAC->h_output_synthesis_psd_params ); + h_dirac_output_synthesis_state = &( hDirAC->h_output_synthesis_psd_state ); + proto_direct_index = hDirAC->proto_index_dir; + num_protos_dir = hDirAC->num_protos_dir; + nchan_out_woLFE = hDirAC->hOutSetup.nchan_out_woLFE; /* collect some often used parameters */ - num_freq_bands = hSpatParamRendCom->num_freq_bands; + num_freq_bands = hDirAC->num_freq_bands; /*-----------------------------------------------------------------* * compute target PSDs *-----------------------------------------------------------------*/ - if ( enc_param_start_band == 0 ) + if ( hDirAC->hConfig->enc_param_start_band == 0 ) { diff_start_band = h_dirac_output_synthesis_params->use_onset_filters == 1 ? h_dirac_output_synthesis_params->max_band_decorr : 0; - if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_MONO ) + if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_MONO ) { nchan_target_psds = 2; } @@ -1305,13 +1301,11 @@ void ivas_dirac_dec_output_synthesis_process_subframe_psd_ls( * compute variables for stereo transport signal type detection *-----------------------------------------------------------------*/ - if ( hDirACRend->masa_stereo_type_detect != NULL ) + if ( hDirAC->masa_stereo_type_detect != NULL ) { - MASA_STEREO_TYPE_DETECT *masa_stereo_type_detect = hDirACRend->masa_stereo_type_detect; - p_cy_auto_dir_smooth = h_dirac_output_synthesis_state->cy_auto_dir_smooth; p_cy_auto_diff_smooth = h_dirac_output_synthesis_state->cy_auto_diff_smooth; - if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_MONO ) + if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_MONO ) { target_power_y = p_cy_auto_dir_smooth[num_freq_bands] / ( sqrtf( h_dirac_output_synthesis_state->direct_power_factor[0] ) + EPSILON ); target_power_y += p_cy_auto_diff_smooth[num_freq_bands] / ( sqrtf( h_dirac_output_synthesis_state->diffuse_power_factor[0] ) + EPSILON ); @@ -1320,19 +1314,19 @@ void ivas_dirac_dec_output_synthesis_process_subframe_psd_ls( { target_power_y = p_cy_auto_dir_smooth[num_freq_bands] + p_cy_auto_diff_smooth[num_freq_bands]; } - subtract_power_y = masa_stereo_type_detect->subtract_power_y; + subtract_power_y = hDirAC->masa_stereo_type_detect->subtract_power_y; a = 0.0004f; /* Temporal smoothing coefficient */ b = 1.0f - a; /* Temporal smoothing coefficient */ - masa_stereo_type_detect->target_power_y_smooth = a * target_power_y + b * masa_stereo_type_detect->target_power_y_smooth; - masa_stereo_type_detect->subtract_power_y_smooth = a * subtract_power_y + b * masa_stereo_type_detect->subtract_power_y_smooth; + hDirAC->masa_stereo_type_detect->target_power_y_smooth = a * target_power_y + b * hDirAC->masa_stereo_type_detect->target_power_y_smooth; + hDirAC->masa_stereo_type_detect->subtract_power_y_smooth = a * subtract_power_y + b * hDirAC->masa_stereo_type_detect->subtract_power_y_smooth; - subtract_target_ratio = masa_stereo_type_detect->subtract_power_y_smooth / ( masa_stereo_type_detect->target_power_y_smooth + EPSILON ); + subtract_target_ratio = hDirAC->masa_stereo_type_detect->subtract_power_y_smooth / ( hDirAC->masa_stereo_type_detect->target_power_y_smooth + EPSILON ); subtract_target_ratio_db = 10.0f * log10f( subtract_target_ratio ); - masa_stereo_type_detect->subtract_target_ratio_db = subtract_target_ratio_db; + hDirAC->masa_stereo_type_detect->subtract_target_ratio_db = subtract_target_ratio_db; - masa_stereo_type_detect->subtract_power_y = 0.0f; + hDirAC->masa_stereo_type_detect->subtract_power_y = 0.0f; } /*-----------------------------------------------------------------* @@ -1741,10 +1735,12 @@ static void ivas_dirac_dec_get_response_split_order( *------------------------------------------------------------------------*/ void ivas_dirac_dec_compute_directional_responses( - SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, /* i/o: common spatial renderer data handle */ - DIRAC_REND_HANDLE hDirACRend, /* i/o: DirAC renderer handle */ - const VBAP_HANDLE hVBAPdata, /* i : VBAP structure */ - const MASA_DECODER_HANDLE hMasa, /* i : MASA decoder structure */ + DIRAC_DEC_HANDLE hDirAC, /* i/o: DirAC handle */ + const VBAP_HANDLE hVBAPdata, /* i : VBAP structure */ + const MASA_DECODER_HANDLE hMasa, /* i : MASA decoder structure */ +#ifdef MASA_AND_OBJECTS + MASA_ISM_DATA_HANDLE hMasaIsm, /* i : MASA_ISM data structure */ +#endif const int16_t *azimuth, const int16_t *elevation, const int16_t md_idx, @@ -1772,24 +1768,29 @@ void ivas_dirac_dec_compute_directional_responses( elevation2 = NULL; transport_signal_type = MASA_STEREO_NOT_DEFINED; - if ( hDirACRend->masa_stereo_type_detect != NULL ) + if ( hDirAC->masa_stereo_type_detect != NULL ) { - dipole_freq_range[0] = hDirACRend->masa_stereo_type_detect->dipole_freq_range[0]; - dipole_freq_range[1] = hDirACRend->masa_stereo_type_detect->dipole_freq_range[1]; - transport_signal_type = hDirACRend->masa_stereo_type_detect->masa_stereo_type; + dipole_freq_range[0] = hDirAC->masa_stereo_type_detect->dipole_freq_range[0]; + dipole_freq_range[1] = hDirAC->masa_stereo_type_detect->dipole_freq_range[1]; + transport_signal_type = hDirAC->masa_stereo_type_detect->masa_stereo_type; } - num_channels_dir = hDirACRend->num_outputs_dir; - if ( hSpatParamRendCom->numSimultaneousDirections == 2 ) + num_channels_dir = hDirAC->num_outputs_dir; +#ifdef MASA_AND_OBJECTS + if ( hDirAC->numParametricDirections == 2 ) +#else + if ( hDirAC->numSimultaneousDirections == 2 ) +#endif { - azimuth2 = hSpatParamRendCom->azimuth2[md_idx]; - elevation2 = hSpatParamRendCom->elevation2[md_idx]; + azimuth2 = hDirAC->azimuth2[md_idx]; + elevation2 = hDirAC->elevation2[md_idx]; } + codingBand = -1; assert( num_channels_dir <= MAX_OUTPUT_CHANNELS && "Number of channels is too high" ); - for ( k = 0; k < hSpatParamRendCom->num_freq_bands; ++k ) + for ( k = 0; k < hDirAC->num_freq_bands; ++k ) { if ( hMasa != NULL && k == MASA_band_grouping_24[hMasa->data.band_mapping[codingBand + 1]] ) { @@ -1798,24 +1799,24 @@ void ivas_dirac_dec_compute_directional_responses( if ( hMasa != NULL && k > MASA_band_grouping_24[hMasa->data.band_mapping[codingBand]] && k < MASA_band_grouping_24[hMasa->data.band_mapping[codingBand + 1]] && - k != hDirACRend->h_output_synthesis_psd_params.max_band_decorr ) + k != hDirAC->h_output_synthesis_psd_params.max_band_decorr ) { /* Panning gains have to be computed only for the first bin of the coding band in MASA, for other bins the previous values can be used */ - if ( hDirACRend->synthesisConf != DIRAC_SYNTHESIS_GAIN_SHD ) + if ( hDirAC->synthesisConf != DIRAC_SYNTHESIS_GAIN_SHD ) { - mvr2r_inc( &hDirACRend->h_output_synthesis_psd_state.direct_responses_square[k - 1], - hSpatParamRendCom->num_freq_bands, &hDirACRend->h_output_synthesis_psd_state.direct_responses_square[k], - hSpatParamRendCom->num_freq_bands, num_channels_dir ); + mvr2r_inc( &hDirAC->h_output_synthesis_psd_state.direct_responses_square[k - 1], + hDirAC->num_freq_bands, &hDirAC->h_output_synthesis_psd_state.direct_responses_square[k], + hDirAC->num_freq_bands, num_channels_dir ); } - mvr2r_inc( &hDirACRend->h_output_synthesis_psd_state.direct_responses[k - 1], - hSpatParamRendCom->num_freq_bands, - &hDirACRend->h_output_synthesis_psd_state.direct_responses[k], - hSpatParamRendCom->num_freq_bands, num_channels_dir ); + mvr2r_inc( &hDirAC->h_output_synthesis_psd_state.direct_responses[k - 1], + hDirAC->num_freq_bands, + &hDirAC->h_output_synthesis_psd_state.direct_responses[k], + hDirAC->num_freq_bands, num_channels_dir ); } else { /* HOA3 PANNING */ - if ( hDirACRend->panningConf == DIRAC_PANNING_HOA3 ) + if ( hDirAC->panningConf == DIRAC_PANNING_HOA3 ) { set_f( direct_response_hoa, 1.0f, MAX_OUTPUT_CHANNELS ); set_f( direct_response_dir2, 1.0f, MAX_OUTPUT_CHANNELS ); @@ -1831,36 +1832,41 @@ void ivas_dirac_dec_compute_directional_responses( } else { - ivas_dirac_dec_get_response( azimuth[k], elevation[k], direct_response_hoa, hDirACRend->hOutSetup.ambisonics_order ); + ivas_dirac_dec_get_response( azimuth[k], elevation[k], direct_response_hoa, hDirAC->hOutSetup.ambisonics_order ); if ( hodirac_flag ) { - ivas_dirac_dec_get_response( azimuth2[k], elevation2[k], direct_response_dir2, hDirACRend->hOutSetup.ambisonics_order ); + ivas_dirac_dec_get_response( azimuth2[k], elevation2[k], direct_response_dir2, hDirAC->hOutSetup.ambisonics_order ); } } - if ( hMasa == NULL && hDirACRend->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) + if ( hMasa == NULL && hDirAC->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) { - mvr2r_inc( direct_response_hoa, 1, &hDirACRend->h_output_synthesis_psd_state.direct_responses[k], hSpatParamRendCom->num_freq_bands, num_channels_dir ); + mvr2r_inc( direct_response_hoa, 1, &hDirAC->h_output_synthesis_psd_state.direct_responses[k], hDirAC->num_freq_bands, num_channels_dir ); if ( hodirac_flag ) { - mvr2r_inc( direct_response_dir2, 1, &hDirACRend->h_output_synthesis_psd_state.direct_responses[k + hSpatParamRendCom->num_freq_bands * num_channels_dir], hSpatParamRendCom->num_freq_bands, num_channels_dir ); + mvr2r_inc( direct_response_dir2, 1, &hDirAC->h_output_synthesis_psd_state.direct_responses[k + hDirAC->num_freq_bands * num_channels_dir], hDirAC->num_freq_bands, num_channels_dir ); } } - else if ( ( ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) && ( hMasa != NULL ) ) || - hDirACRend->synthesisConf == DIRAC_SYNTHESIS_PSD_SHD || hDirACRend->synthesisConf == DIRAC_SYNTHESIS_MONO ) + else if ( ( ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) && ( hMasa != NULL ) ) || + hDirAC->synthesisConf == DIRAC_SYNTHESIS_PSD_SHD || hDirAC->synthesisConf == DIRAC_SYNTHESIS_MONO ) { /* Synthesize the first direction */ - spreadCoherencePanningHoa( azimuth[k], elevation[k], hSpatParamRendCom->spreadCoherence[md_idx][k], direct_response_hoa, num_channels_dir, hDirACRend->hOutSetup.ambisonics_order ); + spreadCoherencePanningHoa( azimuth[k], elevation[k], hDirAC->spreadCoherence[md_idx][k], direct_response_hoa, num_channels_dir, hDirAC->hOutSetup.ambisonics_order ); + /* Synthesize the second direction and combine the gains */ - if ( hSpatParamRendCom->numSimultaneousDirections == 2 ) +#ifdef MASA_AND_OBJECTS + if ( hDirAC->numParametricDirections == 2 ) +#else + if ( hDirAC->numSimultaneousDirections == 2 ) +#endif { - spreadCoherencePanningHoa( azimuth2[k], elevation2[k], hSpatParamRendCom->spreadCoherence2[md_idx][k], direct_response_dir2, num_channels_dir, hDirACRend->hOutSetup.ambisonics_order ); + spreadCoherencePanningHoa( azimuth2[k], elevation2[k], hDirAC->spreadCoherence2[md_idx][k], direct_response_dir2, num_channels_dir, hDirAC->hOutSetup.ambisonics_order ); /* Combine gains from the two directions */ - totalDirect = hSpatParamRendCom->energy_ratio1[md_idx][k] + hSpatParamRendCom->energy_ratio2[md_idx][k] + EPSILON; - directRatio[0] = hSpatParamRendCom->energy_ratio1[md_idx][k] / totalDirect; - directRatio[1] = hSpatParamRendCom->energy_ratio2[md_idx][k] / totalDirect; + totalDirect = hDirAC->energy_ratio1[md_idx][k] + hDirAC->energy_ratio2[md_idx][k] + EPSILON; + directRatio[0] = hDirAC->energy_ratio1[md_idx][k] / totalDirect; + directRatio[1] = hDirAC->energy_ratio2[md_idx][k] / totalDirect; for ( l = 0; l < num_channels_dir; l++ ) { direct_response_hoa[l] *= directRatio[0]; @@ -1868,6 +1874,58 @@ void ivas_dirac_dec_compute_directional_responses( } } +#ifdef MASA_AND_OBJECTS + // Todo OMASA JBM: Here we probably need to use md_idx for meta access + if ( hDirAC->numIsmDirections > 0 ) + { + int16_t dir; + float direct_response_temp[MAX_OUTPUT_CHANNELS]; + float direct_response_ism[MAX_OUTPUT_CHANNELS]; + float masaDirect; + float ismDirect; + + set_zero( direct_response_ism, num_channels_dir ); + + for ( dir = 0; dir < hDirAC->numIsmDirections; dir++ ) + { + if ( hMasaIsm->ism_is_edited[dir] ) + { + ivas_dirac_dec_get_response( hMasaIsm->azimuth_ism_edited[dir], hMasaIsm->elevation_ism_edited[dir], direct_response_temp, hDirAC->hOutSetup.ambisonics_order ); + } + else + { + ivas_dirac_dec_get_response( hMasaIsm->azimuth_ism[dir][hDirAC->dirac_read_idx], hMasaIsm->elevation_ism[dir][hDirAC->dirac_read_idx], direct_response_temp, hDirAC->hOutSetup.ambisonics_order ); + } + + for ( l = 0; l < num_channels_dir; l++ ) + { + direct_response_ism[l] += direct_response_temp[l] * hMasaIsm->energy_ratio_ism[dir][hDirAC->dirac_read_idx][k]; + } + } + + masaDirect = hDirAC->energy_ratio1[hDirAC->dirac_read_idx][k] + EPSILON; + if ( hDirAC->numParametricDirections == 2 ) + { + masaDirect += hDirAC->energy_ratio2[hDirAC->dirac_read_idx][k]; + } + + ismDirect = hMasaIsm->energy_ratio_ism[0][hDirAC->dirac_read_idx][k]; + for ( dir = 1; dir < hDirAC->numIsmDirections; dir++ ) + { + ismDirect += hMasaIsm->energy_ratio_ism[dir][hDirAC->dirac_read_idx][k]; + } + + totalDirect = masaDirect + ismDirect; + directRatio[0] = masaDirect / totalDirect; + directRatio[1] = ismDirect / totalDirect; + for ( l = 0; l < num_channels_dir; l++ ) + { + direct_response_hoa[l] *= directRatio[0]; + direct_response_hoa[l] += directRatio[1] * direct_response_ism[l]; + } + } +#endif + /* Synthesize surrounding coherence */ if ( surCohRatio != NULL && surCohRatio[k] > 0.f ) { @@ -1879,10 +1937,10 @@ void ivas_dirac_dec_compute_directional_responses( /* Set computed gains */ direct_response = direct_response_hoa; - if ( hDirACRend->synthesisConf != DIRAC_SYNTHESIS_GAIN_SHD ) + if ( hDirAC->synthesisConf != DIRAC_SYNTHESIS_GAIN_SHD ) { v_mult( direct_response, direct_response, direct_response_square, num_channels_dir ); - mvr2r_inc( direct_response_square, 1, &hDirACRend->h_output_synthesis_psd_state.direct_responses_square[k], hSpatParamRendCom->num_freq_bands, num_channels_dir ); + mvr2r_inc( direct_response_square, 1, &hDirAC->h_output_synthesis_psd_state.direct_responses_square[k], hDirAC->num_freq_bands, num_channels_dir ); if ( transport_signal_type == MASA_STEREO_SPACED_MICS ) { @@ -1894,33 +1952,38 @@ void ivas_dirac_dec_compute_directional_responses( } else { - set_f( direct_response, 1.0f, hDirACRend->num_protos_ambi ); + set_f( direct_response, 1.0f, hDirAC->num_protos_ambi ); } } - mvr2r_inc( direct_response, 1, &hDirACRend->h_output_synthesis_psd_state.direct_responses[k], hSpatParamRendCom->num_freq_bands, num_channels_dir ); + mvr2r_inc( direct_response, 1, &hDirAC->h_output_synthesis_psd_state.direct_responses[k], hDirAC->num_freq_bands, num_channels_dir ); } else { assert( 0 && "Not supported synthesis method!" ); } } - else if ( hDirACRend->panningConf == DIRAC_PANNING_VBAP ) /*VBAP*/ + else if ( hDirAC->panningConf == DIRAC_PANNING_VBAP ) /*VBAP*/ { /* Synthesize the first direction */ - spreadCoherencePanningVbap( azimuth[k], elevation[k], hSpatParamRendCom->spreadCoherence[md_idx][k], direct_response_ls, num_channels_dir, hVBAPdata ); + spreadCoherencePanningVbap( azimuth[k], elevation[k], hDirAC->spreadCoherence[md_idx][k], direct_response_ls, num_channels_dir, hVBAPdata ); normalizePanningGains( direct_response_ls, num_channels_dir ); /* Synthesize the second direction and combine the gains */ - if ( hSpatParamRendCom->numSimultaneousDirections == 2 ) +#ifdef MASA_AND_OBJECTS + if ( hDirAC->numParametricDirections == 2 ) +#else + if ( hDirAC->numSimultaneousDirections == 2 ) +#endif + { - spreadCoherencePanningVbap( azimuth2[k], elevation2[k], hSpatParamRendCom->spreadCoherence2[md_idx][k], direct_response_dir2, num_channels_dir, hVBAPdata ); + spreadCoherencePanningVbap( azimuth2[k], elevation2[k], hDirAC->spreadCoherence2[md_idx][k], direct_response_dir2, num_channels_dir, hVBAPdata ); normalizePanningGains( direct_response_dir2, num_channels_dir ); /* Combine gains from the two directions */ - totalDirect = hSpatParamRendCom->energy_ratio1[md_idx][k] + hSpatParamRendCom->energy_ratio2[md_idx][k] + EPSILON; - directRatio[0] = hSpatParamRendCom->energy_ratio1[md_idx][k] / totalDirect; - directRatio[1] = hSpatParamRendCom->energy_ratio2[md_idx][k] / totalDirect; + totalDirect = hDirAC->energy_ratio1[md_idx][k] + hDirAC->energy_ratio2[md_idx][k] + EPSILON; + directRatio[0] = hDirAC->energy_ratio1[md_idx][k] / totalDirect; + directRatio[1] = hDirAC->energy_ratio2[md_idx][k] / totalDirect; for ( l = 0; l < num_channels_dir; l++ ) { direct_response_ls[l] *= directRatio[0]; @@ -1929,18 +1992,71 @@ void ivas_dirac_dec_compute_directional_responses( normalizePanningGains( direct_response_ls, num_channels_dir ); } +#ifdef MASA_AND_OBJECTS + // Todo OMASA JBM: Here we also probably need md_idx + if ( hDirAC->numIsmDirections > 0 ) + { + int16_t dir; + float direct_response_temp[MAX_OUTPUT_CHANNELS]; + float direct_response_ism[MAX_OUTPUT_CHANNELS]; + float masaDirect; + float ismDirect; + + set_zero( direct_response_ism, num_channels_dir ); + + for ( dir = 0; dir < hDirAC->numIsmDirections; dir++ ) + { + if ( hMasaIsm->ism_is_edited[dir] ) + { + vbap_determine_gains( hVBAPdata, direct_response_temp, hMasaIsm->azimuth_ism_edited[dir], hMasaIsm->elevation_ism_edited[dir], 1 ); + } + else + { + vbap_determine_gains( hVBAPdata, direct_response_temp, hMasaIsm->azimuth_ism[dir][hDirAC->dirac_read_idx], hMasaIsm->elevation_ism[dir][hDirAC->dirac_read_idx], 1 ); + } + + for ( l = 0; l < num_channels_dir; l++ ) + { + direct_response_ism[l] += direct_response_temp[l] * hMasaIsm->energy_ratio_ism[dir][hDirAC->dirac_read_idx][k]; + } + } + normalizePanningGains( direct_response_ism, num_channels_dir ); + + masaDirect = hDirAC->energy_ratio1[hDirAC->dirac_read_idx][k] + EPSILON; + if ( hDirAC->numParametricDirections == 2 ) + { + masaDirect += hDirAC->energy_ratio2[hDirAC->dirac_read_idx][k]; + } + + ismDirect = hMasaIsm->energy_ratio_ism[0][hDirAC->dirac_read_idx][k]; + for ( dir = 1; dir < hDirAC->numIsmDirections; dir++ ) + { + ismDirect += hMasaIsm->energy_ratio_ism[dir][hDirAC->dirac_read_idx][k]; + } + + totalDirect = masaDirect + ismDirect; + directRatio[0] = masaDirect / totalDirect; + directRatio[1] = ismDirect / totalDirect; + for ( l = 0; l < num_channels_dir; l++ ) + { + direct_response_ls[l] *= directRatio[0]; + direct_response_ls[l] += directRatio[1] * direct_response_ism[l]; + } + normalizePanningGains( direct_response_ls, num_channels_dir ); + } +#endif /* Synthesize surrounding coherence */ if ( surCohRatio != NULL && surCohRatio[k] > 0.f ) { int16_t num_channels_surrCoh; num_channels_surrCoh = num_channels_dir; - num_channels_surrCoh -= hDirACRend->num_ele_spk_no_diffuse_rendering; + num_channels_surrCoh -= hDirAC->num_ele_spk_no_diffuse_rendering; for ( l = 0; l < num_channels_dir; l++ ) { direct_response_ls[l] *= sqrtf( 1.0f - surCohRatio[k] ); - if ( hDirACRend->diffuse_response_function[l] > 0.f ) + if ( hDirAC->diffuse_response_function[l] > 0.f ) { direct_response_ls[l] += sqrtf( surCohRatio[k] / (float) num_channels_surrCoh ); } @@ -1951,8 +2067,8 @@ void ivas_dirac_dec_compute_directional_responses( /* Set computed gains */ direct_response = direct_response_ls; v_mult( direct_response, direct_response, direct_response_square, num_channels_dir ); - mvr2r_inc( direct_response_square, 1, &hDirACRend->h_output_synthesis_psd_state.direct_responses_square[k], hSpatParamRendCom->num_freq_bands, num_channels_dir ); - mvr2r_inc( direct_response, 1, &hDirACRend->h_output_synthesis_psd_state.direct_responses[k], hSpatParamRendCom->num_freq_bands, num_channels_dir ); + mvr2r_inc( direct_response_square, 1, &hDirAC->h_output_synthesis_psd_state.direct_responses_square[k], hDirAC->num_freq_bands, num_channels_dir ); + mvr2r_inc( direct_response, 1, &hDirAC->h_output_synthesis_psd_state.direct_responses[k], hDirAC->num_freq_bands, num_channels_dir ); } else { @@ -2414,12 +2530,21 @@ static void spreadCoherencePanningVbap( return; } +#ifdef MASA_AND_OBJECTS + vbap_determine_gains( hVBAPdata, direct_response, azimuth, elevation, 0 ); +#else vbap_determine_gains( hVBAPdata, direct_response, azimuth, elevation ); +#endif if ( spreadCoh > 0.f ) { +#ifdef MASA_AND_OBJECTS + vbap_determine_gains( hVBAPdata, direct_response_left, azimuth + 30, elevation, 0 ); + vbap_determine_gains( hVBAPdata, direct_response_right, azimuth - 30, elevation, 0 ); +#else vbap_determine_gains( hVBAPdata, direct_response_left, azimuth + 30, elevation ); vbap_determine_gains( hVBAPdata, direct_response_right, azimuth - 30, elevation ); +#endif if ( spreadCoh < 0.5f ) { diff --git a/lib_dec/ivas_init_dec.c b/lib_dec/ivas_init_dec.c index 616069f25fbe1000500cd49ff6179189ab351bcd..111a9ab18b155eab1e4485ea304dbdd0eb81f31b 100644 --- a/lib_dec/ivas_init_dec.c +++ b/lib_dec/ivas_init_dec.c @@ -72,6 +72,7 @@ ivas_error ivas_dec_setup( Decoder_State *st; int32_t ivas_total_brate; ivas_error error; + error = IVAS_ERR_OK; num_bits_read = 0; @@ -163,20 +164,56 @@ ivas_error ivas_dec_setup( /* reconfigure in case a change of operation mode is detected */ if ( ( ivas_total_brate > IVAS_SID_5k2 && ivas_total_brate != st_ivas->hDecoderConfig->last_ivas_total_brate ) || ( st_ivas->ini_active_frame == 0 ) ) { - if ( st_ivas->ini_active_frame == 0 && ivas_total_brate != FRAME_NO_DATA && ivas_total_brate < MASA_STEREO_MIN_BITRATE && st_ivas->nCPE == 1 ) +#ifdef MASA_AND_OBJECTS + if ( st_ivas->last_ivas_format == MASA_FORMAT ) { - st_ivas->hCPE[0]->nchan_out = 1; +#endif + if ( st_ivas->ini_active_frame == 0 && ivas_total_brate != FRAME_NO_DATA && ivas_total_brate < MASA_STEREO_MIN_BITRATE && st_ivas->nCPE == 1 ) + { + st_ivas->hCPE[0]->nchan_out = 1; + } + else + { + if ( ( error = ivas_masa_dec_reconfigure( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + } +#ifdef MASA_AND_OBJECTS } else { - if ( ( error = ivas_masa_dec_reconfigure( st_ivas ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_omasa_dec_config( st_ivas ) ) != IVAS_ERR_OK ) { return error; } } +#endif + } + } + } +#ifdef MASA_AND_OBJECTS + else if ( st_ivas->ivas_format == MASA_ISM_FORMAT ) + { + st_ivas->nchan_transport = 2; /* always 2 MASA transport channels */ + + /* for the DISC mode the number of objects are written at the end of the bitstream, in the MASA metadata */ + st_ivas->nchan_ism = 2 * st_ivas->bit_stream[ivas_total_brate / FRAMES_PER_SEC - 1] + st_ivas->bit_stream[ivas_total_brate / FRAMES_PER_SEC - 2] + 1; + st_ivas->ism_mode = ivas_omasa_ism_mode_select( ivas_total_brate, st_ivas->nchan_ism ); + + if ( st_ivas->ini_frame > 0 ) + { + /* reconfigure in case a change of operation mode is detected */ + if ( ( ivas_total_brate > IVAS_SID_5k2 && ivas_total_brate != st_ivas->hDecoderConfig->last_ivas_total_brate ) || ( st_ivas->ini_active_frame == 0 ) ) + { + if ( ( error = ivas_omasa_dec_config( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } } } } +#endif else if ( st_ivas->ivas_format == MC_FORMAT ) { /* read MC configuration */ @@ -404,9 +441,21 @@ static ivas_error ivas_read_format( { if ( st_ivas->bit_stream[*num_bits_read] ) { +#ifdef MASA_AND_OBJECTS + ( *num_bits_read )++; + if ( st_ivas->bit_stream[*num_bits_read] ) + { + /* Placeholder for SBA + objects */ + } + else + { + st_ivas->ivas_format = MASA_ISM_FORMAT; + } +#else /* placeholder for combined format signaling */ ( *num_bits_read )++; +#endif } ( *num_bits_read )++; @@ -423,6 +472,7 @@ static ivas_error ivas_read_format( st_ivas->ivas_format = SBA_FORMAT; } ( *num_bits_read )++; + break; } } @@ -705,7 +755,11 @@ ivas_error ivas_init_decoder( Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ ) { +#ifdef MASA_AND_OBJECTS + int16_t i, n, k; +#else int16_t i, n; +#endif int16_t sce_id, cpe_id; int16_t numCldfbAnalyses, numCldfbSyntheses; int16_t granularity, n_channels_transport_jbm; @@ -714,6 +768,9 @@ ivas_error ivas_init_decoder( AUDIO_CONFIG output_config; DECODER_CONFIG_HANDLE hDecoderConfig; ivas_error error; +#ifdef MASA_AND_OBJECTS + int32_t ism_total_brate; +#endif error = IVAS_ERR_OK; @@ -727,10 +784,18 @@ ivas_error ivas_init_decoder( if ( output_config == AUDIO_CONFIG_EXTERNAL ) { - if ( !( st_ivas->ism_mode == ISM_MODE_PARAM ) ) +#ifdef OMASA_EXT_OUTPUT + if ( st_ivas->ism_mode == ISM_MASA_MODE_DISC ) + { + hDecoderConfig->nchan_out = st_ivas->nchan_transport + st_ivas->nchan_ism; + } + else +#endif + if ( !( st_ivas->ism_mode == ISM_MODE_PARAM ) ) { hDecoderConfig->nchan_out = st_ivas->nchan_transport; } + st_ivas->hOutSetup.nchan_out_woLFE = hDecoderConfig->nchan_out; } @@ -894,57 +959,82 @@ ivas_error ivas_init_decoder( st_ivas->hSCE[1]->hCoreCoder[0]->hFdCngDec->hFdCngCom->seed3 = st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->seed2; } } - else if ( st_ivas->ivas_format == SBA_FORMAT ) + else if ( st_ivas->ivas_format == SBA_FORMAT || st_ivas->ivas_format == MASA_FORMAT ) { + if ( ( error = ivas_qmetadata_open( &( st_ivas->hQMetaData ) ) ) != IVAS_ERR_OK ) { return error; } - if ( ( error = ivas_spar_dec_open( st_ivas, 0 ) ) != IVAS_ERR_OK ) + if ( st_ivas->ivas_format == MASA_FORMAT ) { - return error; +#ifdef MASA_AND_OBJECTS + /* if we start in ISM_MODE_NONE in MASA_ISM, that appears as normal MASA, but we may change to a mode with ISMs */ + st_ivas->ism_extmeta_active = -1; + st_ivas->ism_extmeta_cnt = 0; +#endif + if ( ( error = ivas_masa_dec_open( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } } - - if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_DEC && st_ivas->hOutSetup.is_loudspeaker_setup ) + else if ( st_ivas->ivas_format == SBA_FORMAT ) { - if ( ( error = ivas_sba_get_hoa_dec_matrix( st_ivas->hOutSetup, &st_ivas->hoa_dec_mtx, st_ivas->hIntSetup.ambisonics_order ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_spar_dec_open( st_ivas, 0 ) ) != IVAS_ERR_OK ) { return error; } - } - if ( ( error = ivas_dirac_sba_config( st_ivas->hQMetaData, &st_ivas->element_mode_init, ivas_total_brate, st_ivas->sba_analysis_order, ivas_get_hodirac_flag( ivas_total_brate, st_ivas->sba_analysis_order ) ? IVAS_MAX_NUM_BANDS : ( IVAS_MAX_NUM_BANDS - SPAR_DIRAC_SPLIT_START_BAND ) ) ) != IVAS_ERR_OK ) - { - return error; - } + if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_DEC && st_ivas->hOutSetup.is_loudspeaker_setup ) + { + if ( ( error = ivas_sba_get_hoa_dec_matrix( st_ivas->hOutSetup, &st_ivas->hoa_dec_mtx, st_ivas->hIntSetup.ambisonics_order ) ) != IVAS_ERR_OK ) + { + return error; + } + } - if ( hDecoderConfig->output_config != AUDIO_CONFIG_FOA && st_ivas->hDecoderConfig->output_config != AUDIO_CONFIG_STEREO && st_ivas->hDecoderConfig->output_config != AUDIO_CONFIG_MONO ) - { - if ( ( error = ivas_dirac_dec_config( st_ivas, DIRAC_OPEN ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_dirac_sba_config( st_ivas->hQMetaData, &st_ivas->element_mode_init, ivas_total_brate, st_ivas->sba_analysis_order, ivas_get_hodirac_flag( ivas_total_brate, st_ivas->sba_analysis_order ) ? IVAS_MAX_NUM_BANDS : ( IVAS_MAX_NUM_BANDS - SPAR_DIRAC_SPLIT_START_BAND ) ) ) != IVAS_ERR_OK ) { return error; } - st_ivas->hSpar->enc_param_start_band = st_ivas->hDirAC->hConfig->enc_param_start_band; - } - else - { - int16_t band_grouping[IVAS_MAX_NUM_BANDS + 1]; + if ( hDecoderConfig->output_config != AUDIO_CONFIG_FOA && st_ivas->hDecoderConfig->output_config != AUDIO_CONFIG_STEREO && st_ivas->hDecoderConfig->output_config != AUDIO_CONFIG_MONO ) + { + if ( ( error = ivas_dirac_dec_open( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } - st_ivas->hSpar->enc_param_start_band = min( IVAS_MAX_NUM_BANDS, SPAR_DIRAC_SPLIT_START_BAND ); - if ( ivas_get_hodirac_flag( ivas_total_brate, st_ivas->sba_analysis_order ) ) + st_ivas->hSpar->enc_param_start_band = st_ivas->hDirAC->hConfig->enc_param_start_band; + } + else { - st_ivas->hSpar->enc_param_start_band = 0; + int16_t band_grouping[IVAS_MAX_NUM_BANDS + 1]; - set_c( (int8_t *) st_ivas->hQMetaData->twoDirBands, (int8_t) 1, st_ivas->hQMetaData->q_direction[0].cfg.nbands ); - st_ivas->hQMetaData->numTwoDirBands = (uint8_t) st_ivas->hQMetaData->q_direction[0].cfg.nbands; + st_ivas->hSpar->enc_param_start_band = min( IVAS_MAX_NUM_BANDS, SPAR_DIRAC_SPLIT_START_BAND ); + if ( ivas_get_hodirac_flag( ivas_total_brate, st_ivas->sba_analysis_order ) ) + { + st_ivas->hSpar->enc_param_start_band = 0; + + set_c( (int8_t *) st_ivas->hQMetaData->twoDirBands, (int8_t) 1, st_ivas->hQMetaData->q_direction[0].cfg.nbands ); + st_ivas->hQMetaData->numTwoDirBands = (uint8_t) st_ivas->hQMetaData->q_direction[0].cfg.nbands; + } + + ivas_dirac_config_bands( band_grouping, IVAS_MAX_NUM_BANDS, (int16_t) ( st_ivas->hDecoderConfig->output_Fs * INV_CLDFB_BANDWIDTH + 0.5f ), + st_ivas->hSpar->dirac_to_spar_md_bands, st_ivas->hQMetaData->useLowerBandRes, st_ivas->hSpar->enc_param_start_band, 0 ); } + st_ivas->sba_dirac_stereo_flag = ivas_get_sba_dirac_stereo_flag( st_ivas ); + } - ivas_dirac_config_bands( band_grouping, IVAS_MAX_NUM_BANDS, (int16_t) ( st_ivas->hDecoderConfig->output_Fs * INV_CLDFB_BANDWIDTH + 0.5f ), - st_ivas->hSpar->dirac_to_spar_md_bands, st_ivas->hQMetaData->useLowerBandRes, st_ivas->hSpar->enc_param_start_band, 0 ); + if ( st_ivas->renderer_type != RENDERER_BINAURAL_MIXER_CONV && st_ivas->renderer_type != RENDERER_BINAURAL_MIXER_CONV_ROOM && + st_ivas->renderer_type != RENDERER_DISABLE && st_ivas->renderer_type != RENDERER_SBA_LINEAR_DEC && st_ivas->ivas_format != SBA_FORMAT ) + { + if ( ( error = ivas_dirac_dec_open( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } } - st_ivas->sba_dirac_stereo_flag = ivas_get_sba_dirac_stereo_flag( st_ivas ); for ( sce_id = 0; sce_id < st_ivas->nSCE; sce_id++ ) { @@ -992,52 +1082,95 @@ ivas_error ivas_init_decoder( /* set CNA/CNG flags */ ivas_sba_set_cna_cng_flag( st_ivas ); } - else if ( st_ivas->ivas_format == MASA_FORMAT ) +#ifdef MASA_AND_OBJECTS + else if ( st_ivas->ivas_format == MASA_ISM_FORMAT ) { + st_ivas->ism_extmeta_active = -1; + st_ivas->ism_extmeta_cnt = 0; + if ( ( error = ivas_qmetadata_open( &( st_ivas->hQMetaData ) ) ) != IVAS_ERR_OK ) { return error; } - if ( ( error = ivas_masa_dec_open( st_ivas ) ) != IVAS_ERR_OK ) + k = 0; + ism_total_brate = 0; + while ( k < SIZE_IVAS_BRATE_TBL && ivas_total_brate != ivas_brate_tbl[k] ) { - return error; + k++; } - if ( st_ivas->renderer_type == RENDERER_DIRAC || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) + if ( st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) { - if ( ( error = ivas_dirac_dec_config( st_ivas, DIRAC_OPEN ) ) != IVAS_ERR_OK ) + /* one separated object */ + st_ivas->nSCE = 1; + + ism_total_brate = sep_object_brate[k - 2][0]; + if ( ( error = create_sce_dec( st_ivas, 0, ism_total_brate ) ) != IVAS_ERR_OK ) { return error; } - } - for ( sce_id = 0; sce_id < st_ivas->nSCE; sce_id++ ) + reset_indices_dec( st_ivas->hSCE[0]->hCoreCoder[0] ); + + if ( ( error = ivas_ism_metadata_dec_create( st_ivas, 1, NULL ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else if ( st_ivas->ism_mode == ISM_MASA_MODE_DISC ) { - if ( ( error = create_sce_dec( st_ivas, sce_id, ivas_total_brate / st_ivas->nchan_transport ) ) != IVAS_ERR_OK ) + int32_t temp_brate[MAX_SCE]; + st_ivas->nSCE = st_ivas->nchan_ism; /* number of objects */ + + for ( sce_id = 0; sce_id < st_ivas->nSCE; sce_id++ ) + { + temp_brate[sce_id] = sep_object_brate[k - 2][st_ivas->nSCE - 1]; + ism_total_brate += temp_brate[sce_id]; + + if ( ( error = create_sce_dec( st_ivas, sce_id, temp_brate[sce_id] ) ) != IVAS_ERR_OK ) + { + return error; + } + + reset_indices_dec( st_ivas->hSCE[sce_id]->hCoreCoder[0] ); + } + + if ( ( error = ivas_ism_metadata_dec_create( st_ivas, st_ivas->nchan_ism, temp_brate ) ) != IVAS_ERR_OK ) { return error; } + } - reset_indices_dec( st_ivas->hSCE[sce_id]->hCoreCoder[0] ); + if ( ( error = ivas_masa_dec_open( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; } - for ( cpe_id = 0; cpe_id < st_ivas->nCPE; cpe_id++ ) + if ( ( error = ivas_masa_ism_data_open( st_ivas ) ) != IVAS_ERR_OK ) { - if ( ( error = create_cpe_dec( st_ivas, cpe_id, ( ivas_total_brate / st_ivas->nchan_transport ) * CPE_CHANNELS ) ) != IVAS_ERR_OK ) + return error; + } + + if ( st_ivas->renderer_type != RENDERER_DISABLE && st_ivas->renderer_type != RENDERER_MONO_DOWNMIX ) + { + if ( ( error = ivas_dirac_dec_open( st_ivas ) ) != IVAS_ERR_OK ) { return error; } + } - for ( n = 0; n < CPE_CHANNELS; n++ ) - { - reset_indices_dec( st_ivas->hCPE[cpe_id]->hCoreCoder[n] ); - } + if ( ( error = create_cpe_dec( st_ivas, 0, ivas_total_brate - ism_total_brate ) ) != IVAS_ERR_OK ) + { + return error; } - /* set CNA/CNG flags */ - ivas_sba_set_cna_cng_flag( st_ivas ); + for ( n = 0; n < CPE_CHANNELS; n++ ) + { + reset_indices_dec( st_ivas->hCPE[0]->hCoreCoder[n] ); + } } +#endif else if ( st_ivas->ivas_format == MC_FORMAT ) { if ( st_ivas->mc_mode == MC_MODE_MCT ) @@ -1144,7 +1277,7 @@ ivas_error ivas_init_decoder( } } - if ( st_ivas->nCPE > 1 ) + if ( st_ivas->nCPE > 1 ) // VE: TBV - is this needed? { if ( ( error = create_mct_dec( st_ivas ) ) != IVAS_ERR_OK ) { @@ -1172,7 +1305,7 @@ ivas_error ivas_init_decoder( if ( st_ivas->renderer_type != RENDERER_DISABLE && st_ivas->renderer_type != RENDERER_MCMASA_MONO_STEREO ) { - if ( ( error = ivas_dirac_dec_config( st_ivas, DIRAC_OPEN ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_dirac_dec_open( st_ivas ) ) != IVAS_ERR_OK ) { return error; } @@ -1188,7 +1321,11 @@ ivas_error ivas_init_decoder( } else { +#ifdef MASA_AND_OBJECTS + vbap_determine_gains( st_ivas->hVBAPdata, st_ivas->hLsSetupCustom->separate_ch_gains, 0, 0, 0 ); +#else vbap_determine_gains( st_ivas->hVBAPdata, st_ivas->hLsSetupCustom->separate_ch_gains, 0, 0 ); +#endif } } @@ -1316,8 +1453,7 @@ ivas_error ivas_init_decoder( } #endif } - /* ParamISM is handled separately from other common config */ - else if ( st_ivas->ivas_format == ISM_FORMAT && st_ivas->ism_mode == ISM_MODE_PARAM && ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) ) + else if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) { if ( st_ivas->renderer_type != RENDERER_STEREO_PARAMETRIC ) { @@ -1487,6 +1623,35 @@ ivas_error ivas_init_decoder( } } +#ifdef MASA_AND_OBJECTS + if ( st_ivas->ivas_format == MASA_ISM_FORMAT ) + { + if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC && st_ivas->ism_mode == ISM_MASA_MODE_DISC ) + { + /* Allocate TD renderer for the objects in DISC mode */ + if ( ( error = ivas_td_binaural_open( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* Allocate 'hIsmRendererData' handle and memory for delay buffer within 'hMasaIsmData' */ + if ( ( error = ivas_masa_ism_separate_object_renderer_open( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + if ( st_ivas->renderer_type == RENDERER_DIRAC && ( st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_DISC ) ) + { + /* Allocate 'hIsmRendererData' handle and memory for delay buffer within 'hMasaIsmData' */ + if ( ( error = ivas_masa_ism_separate_object_renderer_open( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + } + } +#endif + if ( st_ivas->ivas_format == ISM_FORMAT && st_ivas->ism_mode == ISM_MODE_DISC && ( st_ivas->renderer_type == RENDERER_TD_PANNING || @@ -1821,8 +1986,6 @@ void ivas_initialize_handles_dec( ivas_init_split_rend_handles( &st_ivas->splitBinRend.splitrend ); #endif st_ivas->hDiracDecBin = NULL; - st_ivas->hDirACRend = NULL; - st_ivas->hSpatParamRendCom = NULL; st_ivas->hLsSetUpConversion = NULL; st_ivas->hEFAPdata = NULL; st_ivas->hVBAPdata = NULL; @@ -1835,6 +1998,9 @@ void ivas_initialize_handles_dec( st_ivas->hHrtfFastConv = NULL; st_ivas->hHrtfParambin = NULL; st_ivas->hoa_dec_mtx = NULL; +#ifdef MASA_AND_OBJECTS + st_ivas->hMasaIsmData = NULL; +#endif st_ivas->hHeadTrackData = NULL; st_ivas->hHrtfTD = NULL; @@ -1920,7 +2086,11 @@ void ivas_destroy_dec( } /* ISM metadata handles */ +#ifdef MASA_AND_OBJECTS + ivas_ism_metadata_close( st_ivas->hIsmMetaData, 0 ); +#else ivas_ism_metadata_close( st_ivas->hIsmMetaData ); +#endif /* ISM renderer handle */ if ( st_ivas->hIsmRendererData != NULL ) @@ -1933,12 +2103,10 @@ void ivas_destroy_dec( /* DirAC handle */ if ( st_ivas->ivas_format == ISM_FORMAT ) { - ivas_param_ism_dec_close( &( st_ivas->hDirAC ), &( st_ivas->hSpatParamRendCom ), st_ivas->hDecoderConfig->output_config ); + ivas_param_ism_dec_close( &( st_ivas->hDirAC ), st_ivas->hDecoderConfig->output_config ); } else { - ivas_dirac_rend_close( &( st_ivas->hDirACRend ) ); - ivas_spat_hSpatParamRendCom_close( &( st_ivas->hSpatParamRendCom ) ); ivas_dirac_dec_close( &( st_ivas->hDirAC ) ); } @@ -2014,6 +2182,11 @@ void ivas_destroy_dec( st_ivas->hMonoDmxRenderer = NULL; } +#ifdef MASA_AND_OBJECTS + /* MASA ISM structure */ + ivas_masa_ism_data_close( &st_ivas->hMasaIsmData ); +#endif + /* Head track data handle */ ivas_headTrack_close( &st_ivas->hHeadTrackData ); @@ -2094,6 +2267,44 @@ void ivas_init_dec_get_num_cldfb_instances( case RENDERER_BINAURAL_PARAMETRIC: case RENDERER_BINAURAL_PARAMETRIC_ROOM: case RENDERER_STEREO_PARAMETRIC: +#ifdef MASA_AND_OBJECTS + if ( st_ivas->nchan_transport == 1 ) + { + *numCldfbAnalyses = st_ivas->nchan_transport + 1; + } + + if ( st_ivas->mc_mode == MC_MODE_MCMASA && st_ivas->hOutSetup.separateChannelEnabled ) + { + *numCldfbAnalyses = st_ivas->nchan_transport + 1; + } + + if ( st_ivas->ivas_format == MASA_ISM_FORMAT ) + { + if ( st_ivas->ism_mode == ISM_MASA_MODE_DISC ) + { + *numCldfbAnalyses += st_ivas->nchan_ism; + } + else if ( st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) + { + *numCldfbAnalyses = st_ivas->nchan_transport + 1; + } + } + + if ( st_ivas->hDiracDecBin->useTdDecorr ) + { + *numCldfbAnalyses += 2; + } + break; + case RENDERER_NON_DIEGETIC_DOWNMIX: + case RENDERER_MONO_DOWNMIX: + if ( st_ivas->ivas_format == ISM_FORMAT || st_ivas->ivas_format == MASA_ISM_FORMAT ) + { + /* CLDFB not used in rendering */ + *numCldfbAnalyses = 0; + *numCldfbSyntheses = 0; + } + break; +#else if ( st_ivas->nchan_transport == 1 ) { *numCldfbAnalyses = st_ivas->nchan_transport + 1; @@ -2118,6 +2329,7 @@ void ivas_init_dec_get_num_cldfb_instances( *numCldfbSyntheses = 0; } break; +#endif case RENDERER_DIRAC: if ( st_ivas->ivas_format == SBA_FORMAT ) { @@ -2142,7 +2354,7 @@ void ivas_init_dec_get_num_cldfb_instances( { *numCldfbAnalyses = st_ivas->nchan_transport + 1; } - else if ( st_ivas->nchan_transport == 1 && st_ivas->hDirACRend->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) + else if ( st_ivas->nchan_transport == 1 && st_ivas->hDirAC->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) { *numCldfbAnalyses = st_ivas->nchan_transport + 1; } @@ -2355,5 +2567,15 @@ static ivas_error doSanityChecks_IVAS( } #endif +#ifdef OMASA_EXT_OUTPUT + if ( st_ivas->ivas_format == MASA_ISM_FORMAT ) + { + if ( st_ivas->ism_mode != ISM_MASA_MODE_DISC && output_config == AUDIO_CONFIG_EXTERNAL ) + { + return IVAS_ERROR( IVAS_ERR_INVALID_OUTPUT_FORMAT, "Incorrect output configuration specified for combined MASA and ISM format" ); + } + } +#endif + return IVAS_ERR_OK; } diff --git a/lib_dec/ivas_ism_dec.c b/lib_dec/ivas_ism_dec.c index 63464def7f1251008048659757c2a6f21b6228e3..d3d3baa85e59ae52698b779581b8de4b9470d77e 100644 --- a/lib_dec/ivas_ism_dec.c +++ b/lib_dec/ivas_ism_dec.c @@ -76,7 +76,12 @@ static ivas_error ivas_ism_bitrate_switching( ivas_init_dec_get_num_cldfb_instances( st_ivas, &numCldfbAnalyses_old, &numCldfbSyntheses_old ); st_ivas->ism_mode = ism_mode; - if ( ( error = ivas_ism_config( st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->nchan_transport, st_ivas->nchan_ism, NULL, 0, NULL, NULL, element_brate_tmp, NULL, NULL ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_ism_config( st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->nchan_transport, st_ivas->nchan_ism, NULL, 0, NULL, NULL, element_brate_tmp, NULL, NULL +#ifdef MASA_AND_OBJECTS + , + 0 +#endif + ) ) != IVAS_ERR_OK ) { return error; } @@ -122,13 +127,13 @@ static ivas_error ivas_ism_bitrate_switching( if ( st_ivas->hDecoderConfig->voip_active ) { /* transfer subframe info from DirAC or ParamMC to central tc buffer */ - if ( last_ism_mode == ISM_MODE_PARAM && st_ivas->hSpatParamRendCom != NULL && ( st_ivas->renderer_type != RENDERER_MONO_DOWNMIX && st_ivas->renderer_type != RENDERER_DISABLE ) ) + if ( last_ism_mode == ISM_MODE_PARAM && st_ivas->hDirAC != NULL && ( st_ivas->renderer_type != RENDERER_MONO_DOWNMIX && st_ivas->renderer_type != RENDERER_DISABLE ) ) { - st_ivas->hTcBuffer->nb_subframes = st_ivas->hSpatParamRendCom->nb_subframes; - st_ivas->hTcBuffer->subframes_rendered = st_ivas->hSpatParamRendCom->subframes_rendered; - st_ivas->hTcBuffer->num_slots = st_ivas->hSpatParamRendCom->num_slots; - st_ivas->hTcBuffer->slots_rendered = st_ivas->hSpatParamRendCom->slots_rendered; - mvs2s( st_ivas->hSpatParamRendCom->subframe_nbslots, st_ivas->hTcBuffer->subframe_nbslots, MAX_JBM_SUBFRAMES_5MS ); + st_ivas->hTcBuffer->nb_subframes = st_ivas->hDirAC->nb_subframes; + st_ivas->hTcBuffer->subframes_rendered = st_ivas->hDirAC->subframes_rendered; + st_ivas->hTcBuffer->num_slots = st_ivas->hDirAC->num_slots; + st_ivas->hTcBuffer->slots_rendered = st_ivas->hDirAC->slots_rendered; + mvs2s( st_ivas->hDirAC->subframe_nbslots, st_ivas->hTcBuffer->subframe_nbslots, MAX_JBM_SUBFRAMES_5MS ); } /* JBM: when granularity goes down (e.g. Discrete ISM with TD Obj Renderer -> ParamISM with binaural fastconv @@ -169,9 +174,13 @@ static ivas_error ivas_ism_bitrate_switching( if ( st_ivas->ism_mode == ISM_MODE_DISC && last_ism_mode == ISM_MODE_PARAM ) { /* Deallocate the ParamISM struct */ - ivas_param_ism_dec_close( &( st_ivas->hDirAC ), &( st_ivas->hSpatParamRendCom ), st_ivas->hDecoderConfig->output_config ); + ivas_param_ism_dec_close( &( st_ivas->hDirAC ), st_ivas->hDecoderConfig->output_config ); +#ifdef FIX_568_ISM_BITRATE_SWITCHING if ( st_ivas->hOutSetup.output_config == AUDIO_CONFIG_BINAURAL || st_ivas->hOutSetup.output_config == AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) +#else + if ( st_ivas->hOutSetup.output_config == AUDIO_CONFIG_BINAURAL ) +#endif { /* close the parametric binaural renderer */ ivas_dirac_dec_close_binaural_data( &st_ivas->hDiracDecBin ); @@ -210,7 +219,11 @@ static ivas_error ivas_ism_bitrate_switching( } } +#ifdef FIX_568_ISM_BITRATE_SWITCHING if ( st_ivas->hOutSetup.output_config == AUDIO_CONFIG_BINAURAL_ROOM_IR ) +#else + if ( st_ivas->hOutSetup.output_config == AUDIO_CONFIG_BINAURAL_ROOM_IR || st_ivas->hOutSetup.output_config == AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) +#endif { /* close the parametric binaural renderer */ ivas_dirac_dec_close_binaural_data( &st_ivas->hDiracDecBin ); @@ -238,7 +251,11 @@ static ivas_error ivas_ism_bitrate_switching( { return error; } +#ifdef FIX_568_ISM_BITRATE_SWITCHING if ( st_ivas->hOutSetup.output_config == AUDIO_CONFIG_BINAURAL || st_ivas->hOutSetup.output_config == AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) +#else + if ( st_ivas->hOutSetup.output_config == AUDIO_CONFIG_BINAURAL ) +#endif { /* open the parametric binaural renderer */ if ( ( error = ivas_dirac_dec_binaural_copy_hrtfs( &st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) @@ -284,7 +301,11 @@ static ivas_error ivas_ism_bitrate_switching( } } +#ifdef FIX_568_ISM_BITRATE_SWITCHING if ( st_ivas->hOutSetup.output_config == AUDIO_CONFIG_BINAURAL_ROOM_IR ) +#else + if ( st_ivas->hOutSetup.output_config == AUDIO_CONFIG_BINAURAL_ROOM_IR || st_ivas->hOutSetup.output_config == AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) +#endif { /* open the parametric binaural renderer */ if ( ( error = ivas_dirac_dec_binaural_copy_hrtfs( &st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) @@ -353,14 +374,14 @@ static ivas_error ivas_ism_bitrate_switching( } /* transfer subframe info from central tc buffer to ParamMC or McMASA (DirAC) */ - if ( st_ivas->hSpatParamRendCom != NULL ) + if ( st_ivas->hDirAC != NULL ) { - st_ivas->hSpatParamRendCom->nb_subframes = st_ivas->hTcBuffer->nb_subframes; - st_ivas->hSpatParamRendCom->subframes_rendered = st_ivas->hTcBuffer->subframes_rendered; - st_ivas->hSpatParamRendCom->num_slots = st_ivas->hTcBuffer->num_slots; - st_ivas->hSpatParamRendCom->slots_rendered = st_ivas->hTcBuffer->slots_rendered; + st_ivas->hDirAC->nb_subframes = st_ivas->hTcBuffer->nb_subframes; + st_ivas->hDirAC->subframes_rendered = st_ivas->hTcBuffer->subframes_rendered; + st_ivas->hDirAC->num_slots = st_ivas->hTcBuffer->num_slots; + st_ivas->hDirAC->slots_rendered = st_ivas->hTcBuffer->slots_rendered; - mvs2s( st_ivas->hTcBuffer->subframe_nbslots, st_ivas->hSpatParamRendCom->subframe_nbslots, MAX_JBM_SUBFRAMES_5MS ); + mvs2s( st_ivas->hTcBuffer->subframe_nbslots, st_ivas->hDirAC->subframe_nbslots, MAX_JBM_SUBFRAMES_5MS ); } } diff --git a/lib_dec/ivas_ism_metadata_dec.c b/lib_dec/ivas_ism_metadata_dec.c index f5ed58974f3d6aa50c18a1da679b3dfc86859a5c..fb7acc33442155efc8d632d75bda94e8f6854699 100644 --- a/lib_dec/ivas_ism_metadata_dec.c +++ b/lib_dec/ivas_ism_metadata_dec.c @@ -206,9 +206,15 @@ ivas_error ivas_ism_metadata_dec( *----------------------------------------------------------------*/ /* number of objects was read in ivas_dec_setup() */ - st0->next_bit_pos += nchan_ism; +#ifdef MASA_AND_OBJECTS + if ( ism_mode != ISM_MASA_MODE_DISC && ism_mode != ISM_MASA_MODE_MASA_ONE_OBJ ) +#endif + { + /* number of objects was read in ivas_dec_setup() */ + st0->next_bit_pos += nchan_ism; - ism_mode = ivas_ism_mode_select( nchan_ism, ism_total_brate ); + ism_mode = ivas_ism_mode_select( nchan_ism, ism_total_brate ); + } if ( ism_mode == ISM_MODE_PARAM ) { @@ -225,7 +231,11 @@ ivas_error ivas_ism_metadata_dec( } /* read extended metadata presence flag */ +#ifdef MASA_AND_OBJECTS + if ( ism_mode == ISM_MODE_DISC && ism_total_brate >= ISM_EXTENDED_METADATA_BRATE ) +#else if ( ism_total_brate >= ISM_EXTENDED_METADATA_BRATE ) +#endif { ism_extmeta_bitstream = get_next_indice( st0, ISM_EXTENDED_METADATA_BITS ); @@ -255,7 +265,17 @@ ivas_error ivas_ism_metadata_dec( /* Read ISM metadata flags (one per object) */ for ( ch = 0; ch < *nchan_transport; ch++ ) { - ism_imp[ch] = get_next_indice( st0, ISM_METADATA_FLAG_BITS ); +#ifdef MASA_AND_OBJECTS + if ( ism_mode == ISM_MASA_MODE_DISC || ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) + { + /* ISM importance flag is already read in ivas_masa_decode() */ + ism_imp[ch] = hIsmMeta[ch]->ism_imp; + } + else +#endif + { + ism_imp[ch] = get_next_indice( st0, ISM_METADATA_FLAG_BITS ); + } if ( ism_imp[ch] > ISM_NO_META ) { @@ -282,8 +302,17 @@ ivas_error ivas_ism_metadata_dec( { if ( ism_imp[ch] == ISM_NO_META ) { +#ifdef MASA_AND_OBJECTS /* low-rate ISM_NO_META frame */ - null_metadata_flag[ch] = get_next_indice( st0, ISM_METADATA_INACTIVE_FLAG_BITS ); + if ( ism_mode == ISM_MASA_MODE_DISC || ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) + { + null_metadata_flag[ch] = hIsmMeta[ch]->ism_md_null_flag; + } + else +#endif + { + null_metadata_flag[ch] = get_next_indice( st0, ISM_METADATA_INACTIVE_FLAG_BITS ); + } } } @@ -291,17 +320,31 @@ ivas_error ivas_ism_metadata_dec( { if ( ism_imp[ch] == ISM_NO_META ) { - if ( null_metadata_flag[ch] ) +#ifdef MASA_AND_OBJECTS + if ( ism_mode == ISM_MASA_MODE_DISC || ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) { - /* read the true ISM class */ - ism_imp[ch] = get_next_indice( st0, ISM_METADATA_FLAG_BITS ); + lowrate_metadata_flag[ch] = hIsmMeta[ch]->ism_md_lowrate_flag; + + if ( null_metadata_flag[ch] == 0 ) + { + ism_metadata_flag_global |= lowrate_metadata_flag[ch]; + } } else +#endif { - /* read presence of MD in low-rate ISM_NO_META frame flag */ - lowrate_metadata_flag[ch] = get_next_indice( st0, ISM_METADATA_INACTIVE_FLAG_BITS ); + if ( null_metadata_flag[ch] ) + { + /* read the true ISM class */ + ism_imp[ch] = get_next_indice( st0, ISM_METADATA_FLAG_BITS ); + } + else + { + /* read presence of MD in low-rate ISM_NO_META frame flag */ + lowrate_metadata_flag[ch] = get_next_indice( st0, ISM_METADATA_INACTIVE_FLAG_BITS ); - ism_metadata_flag_global |= lowrate_metadata_flag[ch]; + ism_metadata_flag_global |= lowrate_metadata_flag[ch]; + } } } } @@ -324,7 +367,11 @@ ivas_error ivas_ism_metadata_dec( for ( ch = 0; ch < nchan_ism; ch++ ) { hIsmMetaData = hIsmMeta[ch]; +#ifdef MASA_AND_OBJECTS + if ( ism_mode == ISM_MODE_DISC || ism_mode == ISM_MASA_MODE_DISC || ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) +#else if ( ism_mode == ISM_MODE_DISC ) +#endif { nb_bits_start = st0->next_bit_pos; } @@ -410,7 +457,11 @@ ivas_error ivas_ism_metadata_dec( } } /* save number of metadata bits read */ +#ifdef MASA_AND_OBJECTS + if ( ism_mode == ISM_MODE_DISC || ism_mode == ISM_MASA_MODE_DISC || ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) +#else if ( ism_mode == ISM_MODE_DISC ) +#endif { nb_bits_metadata[ch] = st0->next_bit_pos - nb_bits_start; } @@ -494,13 +545,38 @@ ivas_error ivas_ism_metadata_dec( hISMDTX.ism_dtx_hangover_cnt += 1; } +#ifdef MASA_AND_OBJECTS + if ( ism_mode == ISM_MASA_MODE_DISC || ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) + { + ism_metadata_flag_global = 1; + } +#endif + /*----------------------------------------------------------------* * Configuration and decision about bitrates per channel *----------------------------------------------------------------*/ if ( !bfi ) { - if ( ( error = ivas_ism_config( ism_total_brate, *nchan_transport, nchan_ism, hIsmMeta, ism_extmeta_bitstream, null_metadata_flag, ism_imp, element_brate, total_brate, nb_bits_metadata ) ) != IVAS_ERR_OK ) +#ifdef MASA_AND_OBJECTS + int16_t masa_ism_flag = 0; + if ( ism_mode == ISM_MASA_MODE_DISC || ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) + { + masa_ism_flag = 1; + + for ( ch = 0; ch < *nchan_transport; ch++ ) + { + element_brate[ch] = hSCE[ch]->element_brate; + } + } +#endif + + if ( ( error = ivas_ism_config( ism_total_brate, *nchan_transport, nchan_ism, hIsmMeta, ism_extmeta_bitstream, null_metadata_flag, ism_imp, element_brate, total_brate, nb_bits_metadata +#ifdef MASA_AND_OBJECTS + , + masa_ism_flag +#endif + ) ) != IVAS_ERR_OK ) { return error; } @@ -510,16 +586,29 @@ ivas_error ivas_ism_metadata_dec( hIsmMeta[ch]->last_ism_metadata_flag = hIsmMeta[ch]->ism_metadata_flag; hSCE[ch]->hCoreCoder[0]->low_rate_mode = 0; +#ifdef MASA_AND_OBJECTS + if ( ism_mode == ISM_MODE_DISC || ism_mode == ISM_MASA_MODE_DISC || ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) +#else if ( ism_mode == ISM_MODE_DISC ) +#endif { +#ifdef FIX_562_ISM2_64KBPS if ( ism_imp[ch] == ISM_NO_META && ( ( total_brate[ch] < ACELP_8k00 && element_brate[ch] < SCE_CORE_16k_LOW_LIMIT ) || ( total_brate[ch] <= ACELP_16k_LOW_LIMIT && element_brate[ch] >= SCE_CORE_16k_LOW_LIMIT ) ) ) +#else + if ( ism_imp[ch] == ISM_NO_META && total_brate[ch] < ACELP_8k00 ) +#endif { hSCE[ch]->hCoreCoder[0]->low_rate_mode = 1; } } - hSCE[ch]->element_brate = element_brate[ch]; +#ifdef MASA_AND_OBJECTS + if ( ism_mode != ISM_MASA_MODE_DISC && ism_mode != ISM_MASA_MODE_MASA_ONE_OBJ ) +#endif + { + hSCE[ch]->element_brate = element_brate[ch]; + } hSCE[ch]->hCoreCoder[0]->total_brate = total_brate[ch]; } @@ -605,13 +694,31 @@ ivas_error ivas_ism_metadata_dec_create( st_ivas->hIsmMetaData[ch]->last_azimuth = 0; st_ivas->hIsmMetaData[ch]->last_elevation = 0; +#ifdef MASA_AND_OBJECTS + st_ivas->hIsmMetaData[ch]->ism_imp = -1; + st_ivas->hIsmMetaData[ch]->ism_md_null_flag = 0; + st_ivas->hIsmMetaData[ch]->ism_md_lowrate_flag = 0; +#endif + ivas_ism_reset_metadata( st_ivas->hIsmMetaData[ch] ); } - if ( ( error = ivas_ism_config( st_ivas->hDecoderConfig->ivas_total_brate, n_ISms, n_ISms, NULL, 0, NULL, NULL, element_brate_tmp, NULL, NULL ) ) != IVAS_ERR_OK ) +#ifdef MASA_AND_OBJECTS + if ( element_brate_tmp != NULL ) { - return error; +#endif + if ( ( error = ivas_ism_config( st_ivas->hDecoderConfig->ivas_total_brate, n_ISms, n_ISms, NULL, 0, NULL, NULL, element_brate_tmp, NULL, NULL +#ifdef MASA_AND_OBJECTS + , + 0 +#endif + ) ) != IVAS_ERR_OK ) + { + return error; + } +#ifdef MASA_AND_OBJECTS } +#endif st_ivas->hISMDTX.ism_dtx_hangover_cnt = IVAS_ISM_DTX_HO_MAX; diff --git a/lib_dec/ivas_ism_param_dec.c b/lib_dec/ivas_ism_param_dec.c index 8cea5347b448516a5968080d4d7cccd9d79274e0..2497f5ab988c4a042367ec78e5f33961254d897d 100644 --- a/lib_dec/ivas_ism_param_dec.c +++ b/lib_dec/ivas_ism_param_dec.c @@ -287,7 +287,6 @@ static void ivas_param_ism_compute_mixing_matrix( static void ivas_param_ism_render_slot( DIRAC_DEC_HANDLE hDirAC, - SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, float *Cldfb_RealBuffer_in[PARAM_ISM_MAX_DMX], float *Cldfb_ImagBuffer_in[PARAM_ISM_MAX_DMX], float Cldfb_RealBuffer[PARAM_ISM_MAX_CHAN][JBM_CLDFB_SLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], @@ -303,7 +302,7 @@ static void ivas_param_ism_render_slot( tmp_1 = hDirAC->hParamIsmRendering->interpolator[interpolator_idx]; - for ( bin_idx = 0; bin_idx < hSpatParamRendCom->num_freq_bands; bin_idx++ ) + for ( bin_idx = 0; bin_idx < hDirAC->num_freq_bands; bin_idx++ ) { /* smooth the mixing matrix */ for ( outchIdx = 0; outchIdx < num_ch_LS; outchIdx++ ) @@ -325,7 +324,6 @@ static void ivas_param_ism_render_slot( static void ivas_param_ism_rendering( DIRAC_DEC_HANDLE hDirAC, - SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, float Cldfb_RealBuffer_in[PARAM_ISM_MAX_DMX][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], float Cldfb_ImagBuffer_in[PARAM_ISM_MAX_DMX][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], float Cldfb_RealBuffer[PARAM_ISM_MAX_CHAN][4][CLDFB_NO_CHANNELS_MAX], @@ -341,7 +339,7 @@ static void ivas_param_ism_rendering( tmp_1 = hDirAC->hParamIsmRendering->interpolator[slot_idx]; - for ( bin_idx = 0; bin_idx < hSpatParamRendCom->num_freq_bands; bin_idx++ ) + for ( bin_idx = 0; bin_idx < hDirAC->num_freq_bands; bin_idx++ ) { /* smooth the mixing matrix */ for ( outchIdx = 0; outchIdx < num_ch_LS; outchIdx++ ) @@ -442,7 +440,6 @@ ivas_error ivas_param_ism_dec_open( int16_t i; DIRAC_DEC_HANDLE hDirAC; IVAS_OUTPUT_SETUP hOutSetup; - SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom; AUDIO_CONFIG output_config; int32_t output_Fs; ivas_error error; @@ -460,11 +457,6 @@ ivas_error ivas_param_ism_dec_open( return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); } - if ( ( hSpatParamRendCom = (SPAT_PARAM_REND_COMMON_DATA_HANDLE) malloc( sizeof( SPAT_PARAM_REND_COMMON_DATA ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); - } - /* Assign memory to Param Object handle */ if ( ( hDirAC->hParamIsm = (PARAM_ISM_CONFIG_HANDLE) malloc( sizeof( PARAM_ISM_CONFIG_DATA ) ) ) == NULL ) { @@ -485,15 +477,15 @@ ivas_error ivas_param_ism_dec_open( * set input parameters *-----------------------------------------------------------------*/ - hSpatParamRendCom->slot_size = (int16_t) ( ( output_Fs / FRAMES_PER_SEC ) / CLDFB_NO_COL_MAX ); + hDirAC->slot_size = (int16_t) ( ( output_Fs / FRAMES_PER_SEC ) / CLDFB_NO_COL_MAX ); hDirAC->hConfig = NULL; - set_s( hSpatParamRendCom->subframe_nbslots, 0, MAX_JBM_SUBFRAMES_5MS ); - set_s( hSpatParamRendCom->subframe_nbslots, JBM_CLDFB_SLOTS_IN_SUBFRAME, DEFAULT_JBM_SUBFRAMES_5MS ); - hSpatParamRendCom->nb_subframes = DEFAULT_JBM_SUBFRAMES_5MS; - hSpatParamRendCom->subframes_rendered = 0; - hSpatParamRendCom->slots_rendered = 0; - hSpatParamRendCom->num_slots = DEFAULT_JBM_SUBFRAMES_5MS * JBM_CLDFB_SLOTS_IN_SUBFRAME; - hSpatParamRendCom->num_freq_bands = (int16_t) ( output_Fs * INV_CLDFB_BANDWIDTH + 0.5f ); + set_s( hDirAC->subframe_nbslots, 0, MAX_JBM_SUBFRAMES_5MS ); + set_s( hDirAC->subframe_nbslots, JBM_CLDFB_SLOTS_IN_SUBFRAME, DEFAULT_JBM_SUBFRAMES_5MS ); + hDirAC->nb_subframes = DEFAULT_JBM_SUBFRAMES_5MS; + hDirAC->subframes_rendered = 0; + hDirAC->slots_rendered = 0; + hDirAC->num_slots = DEFAULT_JBM_SUBFRAMES_5MS * JBM_CLDFB_SLOTS_IN_SUBFRAME; + hDirAC->num_freq_bands = (int16_t) ( output_Fs * INV_CLDFB_BANDWIDTH + 0.5f ); hDirAC->hParamIsm->nbands = MAX_PARAM_ISM_NBANDS; @@ -501,9 +493,9 @@ ivas_error ivas_param_ism_dec_open( { hDirAC->hParamIsm->band_grouping[i] = Param_ISM_band_grouping[i]; - if ( hDirAC->hParamIsm->band_grouping[i] > hSpatParamRendCom->num_freq_bands ) + if ( hDirAC->hParamIsm->band_grouping[i] > hDirAC->num_freq_bands ) { - hDirAC->hParamIsm->band_grouping[i] = hSpatParamRendCom->num_freq_bands; + hDirAC->hParamIsm->band_grouping[i] = hDirAC->num_freq_bands; } } @@ -554,19 +546,19 @@ ivas_error ivas_param_ism_dec_open( set_zero( hDirAC->azimuth_values, MAX_NUM_OBJECTS ); set_zero( hDirAC->elevation_values, MAX_NUM_OBJECTS ); - hSpatParamRendCom->dirac_md_buffer_length = MAX_PARAM_SPATIAL_SUBFRAMES; - hSpatParamRendCom->dirac_bs_md_write_idx = 0; - hSpatParamRendCom->dirac_read_idx = 0; + hDirAC->dirac_md_buffer_length = MAX_PARAM_SPATIAL_SUBFRAMES; + hDirAC->dirac_bs_md_write_idx = 0; + hDirAC->dirac_read_idx = 0; hDirAC->spar_to_dirac_write_idx = 0; if ( output_config == AUDIO_CONFIG_BINAURAL || output_config == AUDIO_CONFIG_BINAURAL_ROOM_IR || output_config == AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) { - if ( ( error = ivas_dirac_allocate_parameters( hSpatParamRendCom, 1 ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_dirac_allocate_parameters( hDirAC, 1 ) ) != IVAS_ERR_OK ) { return error; } - if ( ( error = ivas_dirac_allocate_parameters( hSpatParamRendCom, 2 ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_dirac_allocate_parameters( hDirAC, 2 ) ) != IVAS_ERR_OK ) { return error; } @@ -575,7 +567,6 @@ ivas_error ivas_param_ism_dec_open( st_ivas->hISMDTX.dtx_flag = 0; st_ivas->hDirAC = hDirAC; - st_ivas->hSpatParamRendCom = hSpatParamRendCom; if ( st_ivas->hDecoderConfig->voip_active ) { @@ -591,17 +582,17 @@ ivas_error ivas_param_ism_dec_open( } else { - if ( ( hDirAC->hParamIsmRendering->Cldfb_RealBuffer_tc = (float *) malloc( MAX_JBM_CLDFB_TIMESLOTS * nchan_transport * hSpatParamRendCom->num_freq_bands * sizeof( float ) ) ) == NULL ) + if ( ( hDirAC->hParamIsmRendering->Cldfb_RealBuffer_tc = (float *) malloc( MAX_JBM_CLDFB_TIMESLOTS * nchan_transport * hDirAC->num_freq_bands * sizeof( float ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Param ISM JBM Rendering handle\n" ) ); } - set_zero( hDirAC->hParamIsmRendering->Cldfb_RealBuffer_tc, MAX_JBM_CLDFB_TIMESLOTS * nchan_transport * hSpatParamRendCom->num_freq_bands ); + set_zero( hDirAC->hParamIsmRendering->Cldfb_RealBuffer_tc, MAX_JBM_CLDFB_TIMESLOTS * nchan_transport * hDirAC->num_freq_bands ); - if ( ( hDirAC->hParamIsmRendering->Cldfb_ImagBuffer_tc = (float *) malloc( MAX_JBM_CLDFB_TIMESLOTS * nchan_transport * hSpatParamRendCom->num_freq_bands * sizeof( float ) ) ) == NULL ) + if ( ( hDirAC->hParamIsmRendering->Cldfb_ImagBuffer_tc = (float *) malloc( MAX_JBM_CLDFB_TIMESLOTS * nchan_transport * hDirAC->num_freq_bands * sizeof( float ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Param ISM JBM Rendering handle\n" ) ); } - set_zero( hDirAC->hParamIsmRendering->Cldfb_ImagBuffer_tc, MAX_JBM_CLDFB_TIMESLOTS * nchan_transport * hSpatParamRendCom->num_freq_bands ); + set_zero( hDirAC->hParamIsmRendering->Cldfb_ImagBuffer_tc, MAX_JBM_CLDFB_TIMESLOTS * nchan_transport * hDirAC->num_freq_bands ); } if ( st_ivas->hTcBuffer == NULL ) { @@ -643,71 +634,67 @@ ivas_error ivas_param_ism_dec_open( *-------------------------------------------------------------------------*/ void ivas_param_ism_dec_close( - DIRAC_DEC_HANDLE *hDirAC_out, /* i/o: decoder DirAC handle */ - SPAT_PARAM_REND_COMMON_DATA_HANDLE *hSpatParamRendCom_out, /* i/o: common spatial renderer data */ - AUDIO_CONFIG output_config /* i : output audio configuration */ + DIRAC_DEC_HANDLE *hDirAC_out, /* i/o: decoder DirAC handle */ + AUDIO_CONFIG output_config /* i : output audio configuration */ ) { - if ( hDirAC_out != NULL && *hDirAC_out != NULL ) + DIRAC_DEC_HANDLE hDirAC; + + if ( hDirAC_out == NULL || *hDirAC_out == NULL ) { - DIRAC_DEC_HANDLE hDirAC; - hDirAC = *hDirAC_out; + return; + } - /* Config & CLDFB */ - if ( hDirAC->hParamIsm != NULL ) - { - free( hDirAC->hParamIsm ); - hDirAC->hParamIsm = NULL; - } + hDirAC = *hDirAC_out; - if ( !( output_config == AUDIO_CONFIG_MONO || output_config == AUDIO_CONFIG_STEREO ) ) - { - /* Param ISM Rendering */ - if ( hDirAC->hParamIsmRendering->interpolator != NULL ) - { - free( hDirAC->hParamIsmRendering->interpolator ); - hDirAC->hParamIsmRendering->interpolator = NULL; - } - if ( hDirAC->hParamIsmRendering->proto_matrix != NULL ) - { - free( hDirAC->hParamIsmRendering->proto_matrix ); - hDirAC->hParamIsmRendering->proto_matrix = NULL; - } - } + /* Config & CLDFB */ + if ( hDirAC->hParamIsm != NULL ) + { + free( hDirAC->hParamIsm ); + hDirAC->hParamIsm = NULL; + } - if ( hDirAC->hParamIsmRendering->Cldfb_RealBuffer_tc != NULL ) - { - free( hDirAC->hParamIsmRendering->Cldfb_RealBuffer_tc ); - hDirAC->hParamIsmRendering->Cldfb_RealBuffer_tc = NULL; - } - if ( hDirAC->hParamIsmRendering->Cldfb_ImagBuffer_tc != NULL ) + if ( output_config == AUDIO_CONFIG_BINAURAL || output_config == AUDIO_CONFIG_BINAURAL_ROOM_IR || output_config == AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) + { + ivas_dirac_deallocate_parameters( hDirAC, 1 ); + ivas_dirac_deallocate_parameters( hDirAC, 2 ); + } + + if ( !( output_config == AUDIO_CONFIG_MONO || output_config == AUDIO_CONFIG_STEREO ) ) + { + /* Param ISM Rendering */ + if ( hDirAC->hParamIsmRendering->interpolator != NULL ) { - free( hDirAC->hParamIsmRendering->Cldfb_ImagBuffer_tc ); - hDirAC->hParamIsmRendering->Cldfb_ImagBuffer_tc = NULL; + free( hDirAC->hParamIsmRendering->interpolator ); + hDirAC->hParamIsmRendering->interpolator = NULL; } - - if ( hDirAC->hParamIsmRendering != NULL ) + if ( hDirAC->hParamIsmRendering->proto_matrix != NULL ) { - free( hDirAC->hParamIsmRendering ); - hDirAC->hParamIsmRendering = NULL; + free( hDirAC->hParamIsmRendering->proto_matrix ); + hDirAC->hParamIsmRendering->proto_matrix = NULL; } - - free( *hDirAC_out ); - *hDirAC_out = NULL; } - if ( hSpatParamRendCom_out != NULL && *hSpatParamRendCom_out != NULL ) + if ( hDirAC->hParamIsmRendering->Cldfb_RealBuffer_tc != NULL ) { - if ( output_config == AUDIO_CONFIG_BINAURAL || output_config == AUDIO_CONFIG_BINAURAL_ROOM_IR || output_config == AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) - { - ivas_dirac_deallocate_parameters( *hSpatParamRendCom_out, 1 ); - ivas_dirac_deallocate_parameters( *hSpatParamRendCom_out, 2 ); - } + free( hDirAC->hParamIsmRendering->Cldfb_RealBuffer_tc ); + hDirAC->hParamIsmRendering->Cldfb_RealBuffer_tc = NULL; + } + if ( hDirAC->hParamIsmRendering->Cldfb_ImagBuffer_tc != NULL ) + { + free( hDirAC->hParamIsmRendering->Cldfb_ImagBuffer_tc ); + hDirAC->hParamIsmRendering->Cldfb_ImagBuffer_tc = NULL; + } - free( *hSpatParamRendCom_out ); - *hSpatParamRendCom_out = NULL; + if ( hDirAC->hParamIsmRendering != NULL ) + { + free( hDirAC->hParamIsmRendering ); + hDirAC->hParamIsmRendering = NULL; } + free( *hDirAC_out ); + *hDirAC_out = NULL; + return; } @@ -726,9 +713,11 @@ void ivas_param_ism_dec( int16_t ch, nchan_transport, nchan_out, nchan_out_woLFE, i; int16_t subframe_idx, slot_idx, index_slot, bin_idx; int32_t ivas_total_brate; +#ifdef FIX_549_DMX_GAIN int16_t output_frame; float gain, ene_tc, ene_sum, grad; float last_gain; +#endif float ref_power[CLDFB_NO_CHANNELS_MAX]; float cx_diag[CLDFB_NO_CHANNELS_MAX][PARAM_ISM_MAX_DMX]; /* CLDFB Input Buffers */ @@ -746,19 +735,18 @@ void ivas_param_ism_dec( float mixing_matrix[CLDFB_NO_CHANNELS_MAX][PARAM_ISM_MAX_CHAN * PARAM_ISM_MAX_DMX]; DIRAC_DEC_HANDLE hDirAC; - SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom; IVAS_OUTPUT_SETUP hSetup; /* Initialization */ hDirAC = st_ivas->hDirAC; assert( hDirAC ); - hSpatParamRendCom = st_ivas->hSpatParamRendCom; - assert( hSpatParamRendCom ); +#ifdef FIX_549_DMX_GAIN ene_tc = 0.0f; ene_sum = 0.0f; last_gain = st_ivas->hDirAC->hParamIsm->last_dmx_gain; output_frame = (int16_t) ( st_ivas->hDecoderConfig->output_Fs / FRAMES_PER_SEC ); +#endif nchan_transport = st_ivas->nchan_transport; if ( st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_EXTERNAL ) @@ -842,6 +830,7 @@ void ivas_param_ism_dec( } } +#ifdef FIX_549_DMX_GAIN /* Energy Compensation */ for ( i = 0; i < output_frame; i++ ) { @@ -875,6 +864,7 @@ void ivas_param_ism_dec( } } st_ivas->hDirAC->hParamIsm->last_dmx_gain = gain; +#endif for ( ch = 0; ch < nchan_transport; ch++ ) { @@ -883,14 +873,14 @@ void ivas_param_ism_dec( *-----------------------------------------------------------------*/ for ( slot_idx = 0; slot_idx < CLDFB_NO_COL_MAX; slot_idx++ ) { - cldfbAnalysis_ts( &( output_f[ch][hSpatParamRendCom->num_freq_bands * slot_idx] ), Cldfb_RealBuffer_in[ch][slot_idx], Cldfb_ImagBuffer_in[ch][slot_idx], hSpatParamRendCom->num_freq_bands, st_ivas->cldfbAnaDec[ch] ); + cldfbAnalysis_ts( &( output_f[ch][hDirAC->num_freq_bands * slot_idx] ), Cldfb_RealBuffer_in[ch][slot_idx], Cldfb_ImagBuffer_in[ch][slot_idx], hDirAC->num_freq_bands, st_ivas->cldfbAnaDec[ch] ); ivas_param_ism_collect_slot( hDirAC, Cldfb_RealBuffer_in[ch][slot_idx], Cldfb_ImagBuffer_in[ch][slot_idx], ch, ref_power, cx_diag ); } } /* Obtain Mixing Matrix on a frame-level */ - for ( bin_idx = 0; bin_idx < hSpatParamRendCom->num_freq_bands; bin_idx++ ) + for ( bin_idx = 0; bin_idx < hDirAC->num_freq_bands; bin_idx++ ) { set_f( mixing_matrix[bin_idx], 0.0f, nchan_transport * nchan_out_woLFE ); } @@ -898,28 +888,28 @@ void ivas_param_ism_dec( /* Compute mixing matrix */ ivas_param_ism_compute_mixing_matrix( st_ivas->nchan_ism, hDirAC, st_ivas->hISMDTX, direct_response, nchan_transport, nchan_out_woLFE, cx_diag, ref_power, mixing_matrix ); /* subframe loop for synthesis*/ - for ( subframe_idx = 0; subframe_idx < hSpatParamRendCom->nb_subframes; subframe_idx++ ) + for ( subframe_idx = 0; subframe_idx < hDirAC->nb_subframes; subframe_idx++ ) { - uint16_t slot_idx_start = subframe_idx * hSpatParamRendCom->subframe_nbslots[subframe_idx]; + uint16_t slot_idx_start = subframe_idx * hDirAC->subframe_nbslots[subframe_idx]; uint16_t idx_in; uint16_t idx_lfe; /* Set some memories to zero */ for ( ch = 0; ch < nchan_out_woLFE; ch++ ) { - for ( slot_idx = 0; slot_idx < hSpatParamRendCom->subframe_nbslots[subframe_idx]; slot_idx++ ) + for ( slot_idx = 0; slot_idx < hDirAC->subframe_nbslots[subframe_idx]; slot_idx++ ) { - set_f( Cldfb_RealBuffer[ch][slot_idx], 0.0f, hSpatParamRendCom->num_freq_bands ); - set_f( Cldfb_ImagBuffer[ch][slot_idx], 0.0f, hSpatParamRendCom->num_freq_bands ); + set_f( Cldfb_RealBuffer[ch][slot_idx], 0.0f, hDirAC->num_freq_bands ); + set_f( Cldfb_ImagBuffer[ch][slot_idx], 0.0f, hDirAC->num_freq_bands ); } } - for ( slot_idx = 0; slot_idx < hSpatParamRendCom->subframe_nbslots[subframe_idx]; slot_idx++ ) + for ( slot_idx = 0; slot_idx < hDirAC->subframe_nbslots[subframe_idx]; slot_idx++ ) { index_slot = slot_idx_start + slot_idx; /* Compute bandwise rendering to target LS using covariance rendering */ - ivas_param_ism_rendering( hDirAC, hSpatParamRendCom, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, + ivas_param_ism_rendering( hDirAC, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, Cldfb_RealBuffer, Cldfb_ImagBuffer, mixing_matrix, slot_idx, index_slot, nchan_out_woLFE, nchan_transport ); } @@ -932,7 +922,7 @@ void ivas_param_ism_dec( { if ( ( hSetup.num_lfe > 0 ) && ( hSetup.index_lfe[idx_lfe] == ch ) ) { - set_zero( &( output_f[ch][slot_idx_start * hSpatParamRendCom->num_freq_bands] ), hSpatParamRendCom->subframe_nbslots[subframe_idx] * hSpatParamRendCom->num_freq_bands ); + set_zero( &( output_f[ch][slot_idx_start * hDirAC->num_freq_bands] ), hDirAC->subframe_nbslots[subframe_idx] * hDirAC->num_freq_bands ); if ( idx_lfe < ( hSetup.num_lfe - 1 ) ) { idx_lfe++; @@ -944,14 +934,14 @@ void ivas_param_ism_dec( float *ImagBuffer[16]; /* open CLDFB buffer up to CLDFB_NO_CHANNELS_MAX bands for 48kHz */ - for ( i = 0; i < hSpatParamRendCom->subframe_nbslots[subframe_idx]; i++ ) + for ( i = 0; i < hDirAC->subframe_nbslots[subframe_idx]; i++ ) { RealBuffer[i] = Cldfb_RealBuffer[idx_in][i]; ImagBuffer[i] = Cldfb_ImagBuffer[idx_in][i]; } - cldfbSynthesis( RealBuffer, ImagBuffer, &( output_f[ch][slot_idx_start * hSpatParamRendCom->num_freq_bands] ), - hSpatParamRendCom->num_freq_bands * hSpatParamRendCom->subframe_nbslots[subframe_idx], st_ivas->cldfbSynDec[ch] ); + cldfbSynthesis( RealBuffer, ImagBuffer, &( output_f[ch][slot_idx_start * hDirAC->num_freq_bands] ), + hDirAC->num_freq_bands * hDirAC->subframe_nbslots[subframe_idx], st_ivas->cldfbSynDec[ch] ); idx_in++; } @@ -1091,25 +1081,26 @@ void ivas_param_ism_dec_digest_tc( int16_t ch, nchan_transport, nchan_out, nchan_out_woLFE, i; int16_t slot_idx, bin_idx; int32_t ivas_total_brate; +#ifdef FIX_549_DMX_GAIN int16_t output_frame; float gain, ene_tc, ene_sum, grad; float last_gain; +#endif float ref_power[CLDFB_NO_CHANNELS_MAX]; float cx_diag[CLDFB_NO_CHANNELS_MAX][PARAM_ISM_MAX_DMX]; /* Direct Response/EFAP Gains */ float direct_response[MAX_NUM_OBJECTS][PARAM_ISM_MAX_CHAN]; DIRAC_DEC_HANDLE hDirAC; - SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom; /* Initialization */ hDirAC = st_ivas->hDirAC; assert( hDirAC ); - hSpatParamRendCom = st_ivas->hSpatParamRendCom; - assert( hSpatParamRendCom ); +#ifdef FIX_549_DMX_GAIN ene_tc = 0.0f; ene_sum = 0.0f; last_gain = st_ivas->hDirAC->hParamIsm->last_dmx_gain; output_frame = (int16_t) ( st_ivas->hDecoderConfig->output_Fs / FRAMES_PER_SEC ); +#endif nchan_transport = st_ivas->nchan_transport; ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; @@ -1196,6 +1187,7 @@ void ivas_param_ism_dec_digest_tc( } } +#ifdef FIX_549_DMX_GAIN /* Energy Compensation */ for ( i = 0; i < output_frame; i++ ) { @@ -1229,6 +1221,7 @@ void ivas_param_ism_dec_digest_tc( } } st_ivas->hDirAC->hParamIsm->last_dmx_gain = gain; +#endif for ( ch = 0; ch < nchan_transport; ch++ ) { @@ -1240,16 +1233,16 @@ void ivas_param_ism_dec_digest_tc( float RealBuffer[CLDFB_NO_CHANNELS_MAX]; float ImagBuffer[CLDFB_NO_CHANNELS_MAX]; - cldfbAnalysis_ts( &( transport_channels_f[ch][hSpatParamRendCom->num_freq_bands * slot_idx] ), RealBuffer, ImagBuffer, hSpatParamRendCom->num_freq_bands, st_ivas->cldfbAnaDec[ch] ); - mvr2r( RealBuffer, &hDirAC->hParamIsmRendering->Cldfb_RealBuffer_tc[slot_idx * hSpatParamRendCom->num_freq_bands * nchan_transport + ch * hSpatParamRendCom->num_freq_bands], hSpatParamRendCom->num_freq_bands ); - mvr2r( ImagBuffer, &hDirAC->hParamIsmRendering->Cldfb_ImagBuffer_tc[slot_idx * hSpatParamRendCom->num_freq_bands * nchan_transport + ch * hSpatParamRendCom->num_freq_bands], hSpatParamRendCom->num_freq_bands ); + cldfbAnalysis_ts( &( transport_channels_f[ch][hDirAC->num_freq_bands * slot_idx] ), RealBuffer, ImagBuffer, hDirAC->num_freq_bands, st_ivas->cldfbAnaDec[ch] ); + mvr2r( RealBuffer, &hDirAC->hParamIsmRendering->Cldfb_RealBuffer_tc[slot_idx * hDirAC->num_freq_bands * nchan_transport + ch * hDirAC->num_freq_bands], hDirAC->num_freq_bands ); + mvr2r( ImagBuffer, &hDirAC->hParamIsmRendering->Cldfb_ImagBuffer_tc[slot_idx * hDirAC->num_freq_bands * nchan_transport + ch * hDirAC->num_freq_bands], hDirAC->num_freq_bands ); ivas_param_ism_collect_slot( hDirAC, RealBuffer, ImagBuffer, ch, ref_power, cx_diag ); } } /* Obtain Mixing Matrix on a frame-level */ - for ( bin_idx = 0; bin_idx < hSpatParamRendCom->num_freq_bands; bin_idx++ ) + for ( bin_idx = 0; bin_idx < hDirAC->num_freq_bands; bin_idx++ ) { set_f( hDirAC->hParamIsmRendering->mixing_matrix_lin[bin_idx], 0.0f, nchan_transport * nchan_out_woLFE ); } @@ -1285,7 +1278,6 @@ static void ivas_ism_param_dec_render_sf( float *Cldfb_RealBuffer_in[PARAM_ISM_MAX_DMX]; float *Cldfb_ImagBuffer_in[PARAM_ISM_MAX_DMX]; DIRAC_DEC_HANDLE hDirAC; - SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom; int16_t slot_idx_start; int16_t idx_in; @@ -1293,32 +1285,31 @@ static void ivas_ism_param_dec_render_sf( int16_t subframe_idx; hDirAC = st_ivas->hDirAC; - hSpatParamRendCom = st_ivas->hSpatParamRendCom; - slot_idx_start = hSpatParamRendCom->slots_rendered; - subframe_idx = hSpatParamRendCom->subframes_rendered; + slot_idx_start = hDirAC->slots_rendered; + subframe_idx = hDirAC->subframes_rendered; /* Set some memories to zero */ for ( ch = 0; ch < nchan_out_woLFE; ch++ ) { - for ( slot_idx = 0; slot_idx < hSpatParamRendCom->subframe_nbslots[subframe_idx]; slot_idx++ ) + for ( slot_idx = 0; slot_idx < hDirAC->subframe_nbslots[subframe_idx]; slot_idx++ ) { - set_f( Cldfb_RealBuffer[ch][slot_idx], 0.0f, hSpatParamRendCom->num_freq_bands ); - set_f( Cldfb_ImagBuffer[ch][slot_idx], 0.0f, hSpatParamRendCom->num_freq_bands ); + set_f( Cldfb_RealBuffer[ch][slot_idx], 0.0f, hDirAC->num_freq_bands ); + set_f( Cldfb_ImagBuffer[ch][slot_idx], 0.0f, hDirAC->num_freq_bands ); } } - for ( slot_idx = 0; slot_idx < hSpatParamRendCom->subframe_nbslots[subframe_idx]; slot_idx++ ) + for ( slot_idx = 0; slot_idx < hDirAC->subframe_nbslots[subframe_idx]; slot_idx++ ) { index_slot = slot_idx_start + slot_idx; for ( ch = 0; ch < nchan_transport; ch++ ) { - Cldfb_RealBuffer_in[ch] = &hDirAC->hParamIsmRendering->Cldfb_RealBuffer_tc[index_slot * hSpatParamRendCom->num_freq_bands * nchan_transport + ch * hSpatParamRendCom->num_freq_bands]; - Cldfb_ImagBuffer_in[ch] = &hDirAC->hParamIsmRendering->Cldfb_ImagBuffer_tc[index_slot * hSpatParamRendCom->num_freq_bands * nchan_transport + ch * hSpatParamRendCom->num_freq_bands]; + Cldfb_RealBuffer_in[ch] = &hDirAC->hParamIsmRendering->Cldfb_RealBuffer_tc[index_slot * hDirAC->num_freq_bands * nchan_transport + ch * hDirAC->num_freq_bands]; + Cldfb_ImagBuffer_in[ch] = &hDirAC->hParamIsmRendering->Cldfb_ImagBuffer_tc[index_slot * hDirAC->num_freq_bands * nchan_transport + ch * hDirAC->num_freq_bands]; } /* Compute bandwise rendering to target LS using covariance rendering */ - ivas_param_ism_render_slot( hDirAC, hSpatParamRendCom, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, + ivas_param_ism_render_slot( hDirAC, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, Cldfb_RealBuffer, Cldfb_ImagBuffer, hDirAC->hParamIsmRendering->mixing_matrix_lin, index_slot, slot_idx, nchan_out_woLFE, nchan_transport ); } @@ -1331,7 +1322,7 @@ static void ivas_ism_param_dec_render_sf( { if ( ( hSetup.num_lfe > 0 ) && ( hSetup.index_lfe[idx_lfe] == ch ) ) { - set_zero( output_f[ch], hSpatParamRendCom->subframe_nbslots[subframe_idx] * hSpatParamRendCom->num_freq_bands ); + set_zero( output_f[ch], hDirAC->subframe_nbslots[subframe_idx] * hDirAC->num_freq_bands ); if ( idx_lfe < ( hSetup.num_lfe - 1 ) ) { idx_lfe++; @@ -1343,19 +1334,19 @@ static void ivas_ism_param_dec_render_sf( float *ImagBuffer[16]; /* open CLDFB buffer up to CLDFB_NO_CHANNELS_MAX bands for 48kHz */ - for ( i = 0; i < hSpatParamRendCom->subframe_nbslots[subframe_idx]; i++ ) + for ( i = 0; i < hDirAC->subframe_nbslots[subframe_idx]; i++ ) { RealBuffer[i] = Cldfb_RealBuffer[idx_in][i]; ImagBuffer[i] = Cldfb_ImagBuffer[idx_in][i]; } cldfbSynthesis( RealBuffer, ImagBuffer, output_f[ch], - hSpatParamRendCom->num_freq_bands * hSpatParamRendCom->subframe_nbslots[subframe_idx], st_ivas->cldfbSynDec[ch] ); + hDirAC->num_freq_bands * hDirAC->subframe_nbslots[subframe_idx], st_ivas->cldfbSynDec[ch] ); idx_in++; } } - hSpatParamRendCom->slots_rendered += hSpatParamRendCom->subframe_nbslots[subframe_idx]; - hSpatParamRendCom->subframes_rendered++; + hDirAC->slots_rendered += hDirAC->subframe_nbslots[subframe_idx]; + hDirAC->subframes_rendered++; return; } @@ -1378,17 +1369,14 @@ void ivas_param_ism_dec_render( int16_t ch, slots_to_render, first_sf, last_sf, subframe_idx; uint16_t slot_size, n_samples_sf; DIRAC_DEC_HANDLE hDirAC; - SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom; IVAS_OUTPUT_SETUP hSetup; int16_t nchan_transport, nchan_out, nchan_out_woLFE; float *output_f_local[MAX_OUTPUT_CHANNELS]; hDirAC = st_ivas->hDirAC; - hSpatParamRendCom = st_ivas->hSpatParamRendCom; hSetup = st_ivas->hIntSetup; #ifdef DEBUGGING assert( hDirAC ); - assert( hSpatParamRendCom ); #endif nchan_transport = st_ivas->nchan_transport; if ( st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_EXTERNAL ) @@ -1405,14 +1393,14 @@ void ivas_param_ism_dec_render( slot_size = NS2SA( st_ivas->hDecoderConfig->output_Fs, CLDFB_SLOT_NS ); /* loop for synthesis, assume we always have to render in multiples of 5ms subframes with spills */ - slots_to_render = min( hSpatParamRendCom->num_slots - hSpatParamRendCom->slots_rendered, nSamplesAsked / slot_size ); + slots_to_render = min( hDirAC->num_slots - hDirAC->slots_rendered, nSamplesAsked / slot_size ); *nSamplesRendered = slots_to_render * slot_size; - first_sf = hSpatParamRendCom->subframes_rendered; + first_sf = hDirAC->subframes_rendered; last_sf = first_sf; while ( slots_to_render > 0 ) { - slots_to_render -= hSpatParamRendCom->subframe_nbslots[last_sf]; + slots_to_render -= hDirAC->subframe_nbslots[last_sf]; last_sf++; } #ifdef DEBUGGING @@ -1427,14 +1415,14 @@ void ivas_param_ism_dec_render( for ( subframe_idx = first_sf; subframe_idx < last_sf; subframe_idx++ ) { ivas_ism_param_dec_render_sf( st_ivas, hSetup, nchan_transport, nchan_out, nchan_out_woLFE, output_f_local ); - n_samples_sf = hSpatParamRendCom->subframe_nbslots[subframe_idx] * hSpatParamRendCom->slot_size; + n_samples_sf = hDirAC->subframe_nbslots[subframe_idx] * st_ivas->hDirAC->slot_size; for ( ch = 0; ch < nchan_out; ch++ ) { output_f_local[ch] += n_samples_sf; } } - if ( hSpatParamRendCom->slots_rendered == hSpatParamRendCom->num_slots ) + if ( hDirAC->slots_rendered == hDirAC->num_slots ) { /* copy the memories */ /* store mixing matrix for next subframe */ @@ -1456,7 +1444,7 @@ void ivas_param_ism_dec_render( } } - *nSamplesAvailable = ( hSpatParamRendCom->num_slots - hSpatParamRendCom->slots_rendered ) * slot_size; + *nSamplesAvailable = ( hDirAC->num_slots - hDirAC->slots_rendered ) * slot_size; return; } @@ -1473,7 +1461,6 @@ void ivas_param_ism_params_to_masa_param_mapping( ) { DIRAC_DEC_HANDLE hDirAC; - SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom; int16_t nBins; int16_t band_idx, bin_idx, sf_idx; int16_t brange[2]; @@ -1483,8 +1470,7 @@ void ivas_param_ism_params_to_masa_param_mapping( int32_t ivas_total_brate; hDirAC = st_ivas->hDirAC; - hSpatParamRendCom = st_ivas->hSpatParamRendCom; - nBins = hSpatParamRendCom->num_freq_bands; + nBins = hDirAC->num_freq_bands; ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; @@ -1506,7 +1492,7 @@ void ivas_param_ism_params_to_masa_param_mapping( float energy_ratio; energy_ratio = powf( st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->coherence, 2.0f ); - hSpatParamRendCom->numSimultaneousDirections = 1; + hDirAC->numSimultaneousDirections = 1; azimuth[0] = (int16_t) roundf( hDirAC->azimuth_values[0] ); elevation[0] = (int16_t) roundf( hDirAC->elevation_values[0] ); @@ -1514,19 +1500,19 @@ void ivas_param_ism_params_to_masa_param_mapping( { for ( bin_idx = 0; bin_idx < nBins; bin_idx++ ) { - hSpatParamRendCom->azimuth[sf_idx][bin_idx] = azimuth[0]; - hSpatParamRendCom->elevation[sf_idx][bin_idx] = elevation[0]; + hDirAC->azimuth[sf_idx][bin_idx] = azimuth[0]; + hDirAC->elevation[sf_idx][bin_idx] = elevation[0]; - hSpatParamRendCom->energy_ratio1[sf_idx][bin_idx] = energy_ratio; + hDirAC->energy_ratio1[sf_idx][bin_idx] = energy_ratio; - hSpatParamRendCom->spreadCoherence[sf_idx][bin_idx] = 0.0f; - hSpatParamRendCom->surroundingCoherence[sf_idx][bin_idx] = 0.0; + hDirAC->spreadCoherence[sf_idx][bin_idx] = 0.0f; + hDirAC->surroundingCoherence[sf_idx][bin_idx] = 0.0; } } } else { - hSpatParamRendCom->numSimultaneousDirections = 2; + hDirAC->numSimultaneousDirections = 2; for ( band_idx = 0; band_idx < hDirAC->hParamIsm->nbands; band_idx++ ) { brange[0] = hDirAC->hParamIsm->band_grouping[band_idx]; @@ -1544,12 +1530,12 @@ void ivas_param_ism_params_to_masa_param_mapping( { for ( bin_idx = brange[0]; bin_idx < brange[1]; bin_idx++ ) { - hSpatParamRendCom->azimuth[sf_idx][bin_idx] = azimuth[0]; - hSpatParamRendCom->elevation[sf_idx][bin_idx] = elevation[0]; - hSpatParamRendCom->energy_ratio1[sf_idx][bin_idx] = power_ratio[0]; - hSpatParamRendCom->azimuth2[sf_idx][bin_idx] = azimuth[1]; - hSpatParamRendCom->elevation2[sf_idx][bin_idx] = elevation[1]; - hSpatParamRendCom->energy_ratio2[sf_idx][bin_idx] = power_ratio[1]; + hDirAC->azimuth[sf_idx][bin_idx] = azimuth[0]; + hDirAC->elevation[sf_idx][bin_idx] = elevation[0]; + hDirAC->energy_ratio1[sf_idx][bin_idx] = power_ratio[0]; + hDirAC->azimuth2[sf_idx][bin_idx] = azimuth[1]; + hDirAC->elevation2[sf_idx][bin_idx] = elevation[1]; + hDirAC->energy_ratio2[sf_idx][bin_idx] = power_ratio[1]; } } } @@ -1558,16 +1544,16 @@ void ivas_param_ism_params_to_masa_param_mapping( { for ( bin_idx = 0; bin_idx < nBins; bin_idx++ ) { - hSpatParamRendCom->spreadCoherence[sf_idx][bin_idx] = 0.0f; - hSpatParamRendCom->spreadCoherence2[sf_idx][bin_idx] = 0.0f; - hSpatParamRendCom->surroundingCoherence[sf_idx][bin_idx] = 0.0; + hDirAC->spreadCoherence[sf_idx][bin_idx] = 0.0f; + hDirAC->spreadCoherence2[sf_idx][bin_idx] = 0.0f; + hDirAC->surroundingCoherence[sf_idx][bin_idx] = 0.0; } } } } else { - hSpatParamRendCom->numSimultaneousDirections = 1; + hDirAC->numSimultaneousDirections = 1; azimuth[0] = (int16_t) roundf( hDirAC->azimuth_values[0] ); elevation[0] = (int16_t) roundf( hDirAC->elevation_values[0] ); @@ -1575,11 +1561,11 @@ void ivas_param_ism_params_to_masa_param_mapping( { for ( bin_idx = 0; bin_idx < nBins; bin_idx++ ) { - hSpatParamRendCom->azimuth[sf_idx][bin_idx] = azimuth[0]; - hSpatParamRendCom->elevation[sf_idx][bin_idx] = elevation[0]; - hSpatParamRendCom->energy_ratio1[sf_idx][bin_idx] = 1.0f; - hSpatParamRendCom->spreadCoherence[sf_idx][bin_idx] = 0.0f; - hSpatParamRendCom->surroundingCoherence[sf_idx][bin_idx] = 0.0; + hDirAC->azimuth[sf_idx][bin_idx] = azimuth[0]; + hDirAC->elevation[sf_idx][bin_idx] = elevation[0]; + hDirAC->energy_ratio1[sf_idx][bin_idx] = 1.0f; + hDirAC->spreadCoherence[sf_idx][bin_idx] = 0.0f; + hDirAC->surroundingCoherence[sf_idx][bin_idx] = 0.0; } } } diff --git a/lib_dec/ivas_ism_renderer.c b/lib_dec/ivas_ism_renderer.c index 77563629aea067143dfffa3946f8dd46547b3afe..9c4479374daa9e2a36fb3476201b59331d5c685d 100644 --- a/lib_dec/ivas_ism_renderer.c +++ b/lib_dec/ivas_ism_renderer.c @@ -338,3 +338,189 @@ void ivas_ism_get_stereo_gains( return; } + + +#ifdef MASA_AND_OBJECTS +/*-------------------------------------------------------------------------* + * ivas_masa_ism_separate_object_renderer_open() + * + * Open structures, reserve memory, and init values. + *-------------------------------------------------------------------------*/ + +ivas_error ivas_masa_ism_separate_object_renderer_open( + Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ +) +{ + int16_t interpolator_length; + int16_t i; + int16_t init_interpolator_length; + + if ( ( st_ivas->hIsmRendererData = (ISM_RENDERER_HANDLE) malloc( sizeof( ISM_RENDERER_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for MASA ISM renderer \n" ) ); + } + + for ( i = 0; i < MAX_NUM_OBJECTS; i++ ) + { + set_f( st_ivas->hIsmRendererData->prev_gains[i], 0.0f, MAX_OUTPUT_CHANNELS ); + } + + // Todo OMASA JBM: This needs touches for VOIP path at least. Current version is mostly an adapted copy from ivas_ism_renderer_open() + if ( st_ivas->hDecoderConfig->voip_active ) + { + init_interpolator_length = NS2SA( st_ivas->hDecoderConfig->output_Fs, MAX_JBM_CLDFB_TIMESLOTS * CLDFB_SLOT_NS ); + interpolator_length = (int16_t) ( st_ivas->hDecoderConfig->output_Fs / FRAMES_PER_SEC / MAX_PARAM_SPATIAL_SUBFRAMES ); + } + else + { + init_interpolator_length = (int16_t) ( st_ivas->hDecoderConfig->output_Fs / FRAMES_PER_SEC / MAX_PARAM_SPATIAL_SUBFRAMES ); + interpolator_length = init_interpolator_length; + } + st_ivas->hIsmRendererData->interpolator = (float *) malloc( sizeof( float ) * init_interpolator_length ); + + for ( i = 0; i < interpolator_length; i++ ) + { + st_ivas->hIsmRendererData->interpolator[i] = (float) i / ( (float) interpolator_length ); + } + + st_ivas->hMasaIsmData->delayBuffer_size = (int16_t) ( ( st_ivas->hDecoderConfig->output_Fs / 50 ) / MAX_PARAM_SPATIAL_SUBFRAMES ); + + if ( st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) + { + st_ivas->hMasaIsmData->delayBuffer_nchan = 1; + } + else + { + st_ivas->hMasaIsmData->delayBuffer_nchan = st_ivas->nchan_ism; + } + + if ( ( st_ivas->hMasaIsmData->delayBuffer = (float **) malloc( st_ivas->hMasaIsmData->delayBuffer_nchan * sizeof( float * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for MASA ISM delay buffer \n" ) ); + } + + for ( i = 0; i < st_ivas->hMasaIsmData->delayBuffer_nchan; i++ ) + { + if ( ( st_ivas->hMasaIsmData->delayBuffer[i] = (float *) malloc( st_ivas->hMasaIsmData->delayBuffer_size * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for MASA ISM delay buffer \n" ) ); + } + set_zero( st_ivas->hMasaIsmData->delayBuffer[i], st_ivas->hMasaIsmData->delayBuffer_size ); + } + + return IVAS_ERR_OK; +} + + +/*-------------------------------------------------------------------------* + * ivas_masa_ism_separate_object_render() + * + * Rendering separated objects and mixing them to the parametrically rendered signals + *-------------------------------------------------------------------------*/ + +// Todo OMASA JBM: This might need adjustments +void ivas_masa_ism_separate_object_render( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + float input_f[][L_FRAME48k], /* i : separated object signal */ + float output_f[][L_FRAME48k], /* i/o: output signals */ + const int16_t output_frame /* i : output frame length per channel */ +) +{ + VBAP_HANDLE hVBAPdata; + int16_t nchan_out_woLFE; + ISM_RENDERER_HANDLE hRendererData; + int16_t j, k, j2; + int16_t obj; + float gains[MAX_OUTPUT_CHANNELS]; + float g1, g2; + int16_t lfe_index; + int16_t azimuth, elevation; + int16_t num_objects; + uint8_t single_separated; + int16_t block; + int16_t subframe_len; + int16_t idx_offset; + int16_t dirac_read_idx; + + hVBAPdata = st_ivas->hVBAPdata; + nchan_out_woLFE = st_ivas->hIntSetup.nchan_out_woLFE; + hRendererData = st_ivas->hIsmRendererData; + lfe_index = st_ivas->hDirAC->hOutSetup.index_lfe[0]; + subframe_len = output_frame / MAX_PARAM_SPATIAL_SUBFRAMES; + + if ( st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) + { + single_separated = 1; + num_objects = 1; + } + else + { + single_separated = 0; + num_objects = st_ivas->nchan_ism; + } + + for ( obj = 0; obj < num_objects; obj++ ) + { + delay_signal( input_f[obj], output_frame, st_ivas->hMasaIsmData->delayBuffer[obj], st_ivas->hMasaIsmData->delayBuffer_size ); /* Delay the signal to match CLDFB delay */ + + for ( block = 0; block < MAX_PARAM_SPATIAL_SUBFRAMES; block++ ) + { + idx_offset = block * subframe_len; + dirac_read_idx = ( st_ivas->hDirAC->dirac_read_idx + block ) % st_ivas->hDirAC->dirac_md_buffer_length; + + if ( single_separated ) + { + azimuth = st_ivas->hMasaIsmData->azimuth_separated_ism[dirac_read_idx]; + elevation = st_ivas->hMasaIsmData->elevation_separated_ism[dirac_read_idx]; + } + else + { + azimuth = st_ivas->hMasaIsmData->azimuth_ism[obj][dirac_read_idx]; + elevation = st_ivas->hMasaIsmData->elevation_ism[obj][dirac_read_idx]; + } + + if ( st_ivas->hOutSetup.is_planar_setup ) + { + /* If no elevation support in output format, then rendering should be done with zero elevation */ + elevation = 0; + } + + if ( hVBAPdata != NULL ) + { + vbap_determine_gains( hVBAPdata, gains, azimuth, elevation, 1 ); + } + else + { + ivas_dirac_dec_get_response( azimuth, elevation, gains, st_ivas->hDirAC->hOutSetup.ambisonics_order ); + } + + for ( j = 0; j < nchan_out_woLFE; j++ ) + { + if ( st_ivas->hDirAC->hOutSetup.num_lfe > 0 ) + { + j2 = j + ( j >= lfe_index ); + } + else + { + j2 = j; + } + + if ( fabsf( gains[j] ) > 0.0f || fabsf( hRendererData->prev_gains[obj][j] ) > 0.0f ) + { + for ( k = 0; k < subframe_len; k++ ) + { + g1 = hRendererData->interpolator[k]; + g2 = 1.0f - g1; + output_f[j2][k + idx_offset] += ( g1 * gains[j] + g2 * hRendererData->prev_gains[obj][j] ) * input_f[obj][k + idx_offset]; + } + } + hRendererData->prev_gains[obj][j] = gains[j]; + } + } + } + + st_ivas->hDirAC->dirac_read_idx = ( st_ivas->hDirAC->dirac_read_idx + MAX_PARAM_SPATIAL_SUBFRAMES ) % st_ivas->hDirAC->dirac_md_buffer_length; + + return; +} +#endif diff --git a/lib_dec/ivas_jbm_dec.c b/lib_dec/ivas_jbm_dec.c index e1a7a9cbd28640a5357caa7cc844d572d8042af5..98b0672af362fe780fa5aab249eff7b45a88ed11 100644 --- a/lib_dec/ivas_jbm_dec.c +++ b/lib_dec/ivas_jbm_dec.c @@ -320,7 +320,7 @@ ivas_error ivas_jbm_dec_tc( { #ifdef FIX_564 /* loudness correction */ - ivas_dirac_dec_binaural_sba_gain( output, nchan_remapped, output_frame ); + ivas_dirac_dec_binaural_gain( output, nchan_remapped, output_frame ); #else float gain = 0.8414f; /* Todo: Temporary gain for roughly matching the loudness. To be tuned later together with other outputs. Also, this is not inline with ivas_dec() */ @@ -691,7 +691,6 @@ ivas_error ivas_jbm_dec_render( ivas_error error; float *p_output[MAX_OUTPUT_CHANNELS]; float *p_tc[MAX_TRANSPORT_CHANNELS]; - SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom; error = IVAS_ERR_OK; @@ -701,7 +700,6 @@ ivas_error ivas_jbm_dec_render( * Initialization of local vars after struct has been set *----------------------------------------------------------------*/ - hSpatParamRendCom = st_ivas->hSpatParamRendCom; output_Fs = st_ivas->hDecoderConfig->output_Fs; nchan_out = st_ivas->hDecoderConfig->nchan_out; nchan_transport = st_ivas->hTcBuffer->nchan_transport_jbm; @@ -969,7 +967,7 @@ ivas_error ivas_jbm_dec_render( } else if ( st_ivas->mc_mode == MC_MODE_MCMASA ) { - int16_t offset = hSpatParamRendCom->slots_rendered * hSpatParamRendCom->slot_size; + int16_t offset = st_ivas->hDirAC->slots_rendered * st_ivas->hDirAC->slot_size; nchan_remapped = st_ivas->nchan_transport; if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) diff --git a/lib_dec/ivas_masa_dec.c b/lib_dec/ivas_masa_dec.c index 4a6053ccd5b44aa3ccf191ecb847ed553d4eea41..1c9cc56417f48ae45fbafc1ac2ce6bfca5f8fea2 100644 --- a/lib_dec/ivas_masa_dec.c +++ b/lib_dec/ivas_masa_dec.c @@ -35,7 +35,6 @@ #include #include "ivas_cnst.h" #include "ivas_prot.h" -#include "ivas_prot_rend.h" #include "ivas_rom_com.h" #include "ivas_stat_dec.h" #include "prot.h" @@ -73,6 +72,16 @@ static int16_t decode_lfe_to_total_energy_ratio( MCMASA_LFE_SYNTH_DATA_HANDLE hM static ivas_error ivas_masa_dec_config( Decoder_Struct *st_ivas ); +#ifdef MASA_AND_OBJECTS +static int16_t ivas_decode_masaism_metadata( IVAS_QMETADATA_HANDLE hQMetaData, MASA_DECODER_HANDLE hMasa, MASA_ISM_DATA_HANDLE hMasaIsmData, const int16_t nchan_ism, uint16_t *bit_stream, int16_t *next_bit_pos, const int16_t idx_separated_object, const int16_t ism_imp, const int16_t dirac_bs_md_write_idx, const int16_t dirac_md_buffer_length ); + +static void decode_index_slice( int16_t index, int16_t *ratio_idx_ism, const int16_t nchan_ism, const int16_t K ); + +static void decode_ism_ratios( uint16_t *bit_stream, int16_t *next_bit_pos, IVAS_QMETADATA_HANDLE hQMetaData, float ratio_ism[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS], const int16_t nchan_ism, const int16_t nbands, const int16_t nblocks, const int16_t idx_separated_object ); + +static void read_ism_ratio_index( int16_t ratio_ism_idx[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS], const int16_t nchan_ism, const int16_t numCodingBands, const int16_t sf, int16_t ratio_ism_idx_prev_sf[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS], uint16_t *bit_stream, int16_t *next_bit_pos, float *masa_to_total_energy_ratio, const int16_t idx_sep_obj, int16_t *num_zeros ); +#endif + /*-----------------------------------------------------------------------* * ivas_masa_decode() @@ -94,13 +103,26 @@ ivas_error ivas_masa_decode( IVAS_FORMAT ivas_format; int16_t low_bitrate_mode, tmp_elem_mode; ivas_error error; +#ifdef MASA_AND_OBJECTS + int16_t obj; + int16_t i, ch, ism_imp; + int16_t dirac_bs_md_write_idx; + int32_t masa_total_brate; + + dirac_bs_md_write_idx = 0; + ism_imp = 0; +#endif error = IVAS_ERR_OK; ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; low_bitrate_mode = -1; /* This means that LBR mode is not used. */ +#ifdef MASA_AND_OBJECTS + if ( st_ivas->hOutSetup.separateChannelEnabled || st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_DISC ) +#else if ( st_ivas->hOutSetup.separateChannelEnabled ) +#endif { masa_brate = st_ivas->hCPE[0]->element_brate; } @@ -131,10 +153,109 @@ ivas_error ivas_masa_decode( { if ( !( ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCMASA ) ) { - /* the number of MASA transport channels was read in ivas_dec_setup() */ - st->next_bit_pos -= MASA_TRANSP_BITS; - *nb_bits_read += MASA_TRANSP_BITS; +#ifdef MASA_AND_OBJECTS + if ( ivas_format != MASA_ISM_FORMAT ) + { + /* number of transport channels is always 2 for MASA_ISM format */ +#endif + /* the number of MASA transport channels was read in ivas_dec_setup() */ + st->next_bit_pos -= MASA_TRANSP_BITS; + *nb_bits_read += MASA_TRANSP_BITS; +#ifdef MASA_AND_OBJECTS + } +#endif + +#ifdef MASA_AND_OBJECTS + if ( ivas_format == MASA_ISM_FORMAT && st_ivas->ism_mode != ISM_MODE_NONE ) + { + /* the number of objects was read */ + st->next_bit_pos -= NO_BITS_MASA_ISM_NO_OBJ; + *nb_bits_read += NO_BITS_MASA_ISM_NO_OBJ; + + if ( st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) + { + /* read index of separated object */ + /* nchan_ism should be > 1*/ + byteBuffer = st->bit_stream[( st->next_bit_pos )--]; + ( *nb_bits_read )++; + st_ivas->hMasaIsmData->idx_separated_ism = 2 * byteBuffer + st->bit_stream[( st->next_bit_pos )--]; + ( *nb_bits_read )++; + } + else + { + st_ivas->hMasaIsmData->idx_separated_ism = -1; + } + + /* read ISM importance flag (one per object) */ + if ( st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) + { + ism_imp = 0; + for ( i = 0; i < ISM_METADATA_FLAG_BITS; i++ ) + { + byteBuffer = st->bit_stream[( st->next_bit_pos )--]; + ( *nb_bits_read )++; + ism_imp = ( ism_imp << 1 ) + byteBuffer; + } + st_ivas->hIsmMetaData[0]->ism_imp = ism_imp; + } + + if ( st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) + { + ism_imp = 0; + for ( i = 0; i < ISM_METADATA_FLAG_BITS; i++ ) + { + byteBuffer = st->bit_stream[( st->next_bit_pos )--]; + ( *nb_bits_read )++; + ism_imp = ( ism_imp << 1 ) + byteBuffer; + } + st_ivas->hIsmMetaData[0]->ism_imp = ism_imp; + /* reset */ + st_ivas->hIsmMetaData[0]->ism_md_null_flag = 0; + st_ivas->hIsmMetaData[0]->ism_md_lowrate_flag = 0; + if ( st_ivas->hIsmMetaData[0]->ism_imp == ISM_NO_META ) + { + /* read flags */ + st_ivas->hIsmMetaData[0]->ism_md_null_flag = st->bit_stream[( st->next_bit_pos )--]; + ( *nb_bits_read ) += ISM_METADATA_MD_FLAG_BITS; + st_ivas->hIsmMetaData[0]->ism_md_lowrate_flag = st->bit_stream[( st->next_bit_pos )--]; + ( *nb_bits_read ) += ISM_METADATA_INACTIVE_FLAG_BITS; + } + } + else if ( st_ivas->ism_mode == ISM_MASA_MODE_DISC ) + { + for ( ch = 0; ch < st_ivas->nchan_ism; ch++ ) + { + ism_imp = 0; + for ( i = 0; i < ISM_METADATA_FLAG_BITS; i++ ) + { + byteBuffer = st->bit_stream[( st->next_bit_pos )--]; + ( *nb_bits_read )++; + ism_imp = ( ism_imp << 1 ) + byteBuffer; + } + st_ivas->hIsmMetaData[ch]->ism_imp = ism_imp; + + /* reset */ + st_ivas->hIsmMetaData[ch]->ism_md_null_flag = 0; + st_ivas->hIsmMetaData[ch]->ism_md_lowrate_flag = 0; + if ( st_ivas->hIsmMetaData[ch]->ism_imp == ISM_NO_META ) + { + /* read flags */ + st_ivas->hIsmMetaData[ch]->ism_md_null_flag = st->bit_stream[( st->next_bit_pos )--]; + ( *nb_bits_read ) += ISM_METADATA_MD_FLAG_BITS; + st_ivas->hIsmMetaData[ch]->ism_md_lowrate_flag = st->bit_stream[( st->next_bit_pos )--]; + ( *nb_bits_read ) += ISM_METADATA_INACTIVE_FLAG_BITS; + } + } + st_ivas->flag_omasa_brate = 0; + if ( st_ivas->nchan_ism >= 3 && ivas_total_brate == IVAS_128k ) + { + st_ivas->flag_omasa_brate = st->bit_stream[( st->next_bit_pos )--]; + ( *nb_bits_read ) += 1; + } + } + } +#endif /* Placeholder for descriptive metadata content */ byteBuffer = st->bit_stream[( st->next_bit_pos )--]; byteBuffer += st->bit_stream[( st->next_bit_pos )--]; @@ -193,9 +314,57 @@ ivas_error ivas_masa_decode( /* Remove already read bits from the bit budget */ hQMetaData->metadata_max_bits -= *nb_bits_read; + +#ifdef MASA_AND_OBJECTS + if ( st_ivas->ivas_format == MASA_ISM_FORMAT ) + { + if ( st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) + { + if ( st_ivas->hDirAC != NULL ) + { + *nb_bits_read += ivas_decode_masaism_metadata( hQMetaData, st_ivas->hMasa, st_ivas->hMasaIsmData, st_ivas->nchan_ism, st->bit_stream, &st->next_bit_pos, + st_ivas->hMasaIsmData->idx_separated_ism, ism_imp, st_ivas->hDirAC->dirac_bs_md_write_idx, st_ivas->hDirAC->dirac_md_buffer_length ); + + for ( obj = 0; obj <= st_ivas->nchan_ism; obj++ ) + { + if ( st_ivas->hMasaIsmData->idx_separated_ism == obj ) + { + int16_t sf; + int16_t meta_write_index; + + for ( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ ) + { + meta_write_index = ( st_ivas->hDirAC->dirac_bs_md_write_idx + sf ) % st_ivas->hDirAC->dirac_md_buffer_length; + st_ivas->hMasaIsmData->azimuth_separated_ism[meta_write_index] = st_ivas->hMasaIsmData->azimuth_ism[obj][meta_write_index]; + st_ivas->hMasaIsmData->elevation_separated_ism[meta_write_index] = st_ivas->hMasaIsmData->elevation_ism[obj][meta_write_index]; + } + } + } + } + else + { + *nb_bits_read += ivas_decode_masaism_metadata( hQMetaData, st_ivas->hMasa, st_ivas->hMasaIsmData, st_ivas->nchan_ism, st->bit_stream, &st->next_bit_pos, + st_ivas->hMasaIsmData->idx_separated_ism, ism_imp, 0, MAX_PARAM_SPATIAL_SUBFRAMES ); + } + } + } +#endif + +#ifdef MASA_AND_OBJECTS + masa_total_brate = ivas_total_brate; + if ( ivas_format == MASA_ISM_FORMAT && st_ivas->ism_mode == ISM_MASA_MODE_DISC ) + { + masa_total_brate = calculate_cpe_brate_MASA_ISM( st_ivas->ism_mode, ivas_total_brate, st_ivas->nchan_ism ); + } + + if ( masa_total_brate >= IVAS_384k ) + { + if ( masa_total_brate >= IVAS_512k ) +#else if ( ivas_total_brate >= IVAS_384k ) { if ( ivas_total_brate >= IVAS_512k ) +#endif { *nb_bits_read += ivas_qmetadata_dec_decode_hr_384_512( hQMetaData, st->bit_stream, &st->next_bit_pos, hMasa->data.sph_grid16, 16, 4, hMasa->config.numCodingBands ); } @@ -209,6 +378,14 @@ ivas_error ivas_masa_decode( *nb_bits_read += ivas_qmetadata_dec_decode( hQMetaData, st->bit_stream, &st->next_bit_pos, 0 ); } +#ifdef MASA_AND_OBJECTS + if ( st_ivas->ivas_format == MASA_ISM_FORMAT && st_ivas->ism_mode != ISM_MASA_MODE_DISC && st_ivas->ism_mode != ISM_MASA_MODE_MASA_ONE_OBJ ) + { + /* Modify spatial metadata based on the MASA-to-total energy ratios */ + modify_masa_energy_ratios( hQMetaData ); + } +#endif + /* Get direction decoding quality. EC 1 and 2 are handled by the default value. */ if ( hQMetaData->ec_flag == 2 ) { @@ -242,7 +419,12 @@ ivas_error ivas_masa_decode( return error; } - ivas_masa_set_elements( ivas_total_brate, st_ivas->mc_mode, st_ivas->nchan_transport, hQMetaData, &st_ivas->element_mode_init, &st_ivas->nSCE, &st_ivas->nCPE ); + ivas_masa_set_elements( ivas_total_brate, st_ivas->mc_mode, st_ivas->nchan_transport, hQMetaData, &st_ivas->element_mode_init, &st_ivas->nSCE, &st_ivas->nCPE +#ifdef MASA_AND_OBJECTS + , + st_ivas->ivas_format, st_ivas->ism_mode, 0 +#endif + ); hQMetaData->metadata_max_bits = ( IVAS_SID_5k2 - SID_2k40 ) / FRAMES_PER_SEC; @@ -286,21 +468,93 @@ ivas_error ivas_masa_decode( } } } + if ( st_ivas->hDirAC != NULL ) { - ivas_qmetadata_to_dirac( hQMetaData, st_ivas->hDirAC, hMasa, st_ivas->hSpatParamRendCom, ivas_total_brate, ivas_format, 0, 0 ); +#ifdef MASA_AND_OBJECTS + // Todo OMASA JBM: This might need adjustments + dirac_bs_md_write_idx = st_ivas->hDirAC->dirac_bs_md_write_idx; /* Store the write-index for this frame */ +#endif + + ivas_qmetadata_to_dirac( hQMetaData, st_ivas->hDirAC, hMasa, ivas_total_brate, ivas_format, 0, 0 ); + } + +#ifdef MASA_AND_OBJECTS + if ( st_ivas->ivas_format == MASA_ISM_FORMAT ) + { + if ( hQMetaData->q_direction == NULL ) + { + if ( ( error = ivas_masa_dec_config( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + if ( st_ivas->hDirAC != NULL ) + { + int16_t b; + int16_t block; + int16_t meta_write_index; + + for ( i = 0; i < st_ivas->hDirAC->numIsmDirections; i++ ) /* Todo Nokia: Probably there is a better place for this eventually */ + { + for ( block = 0; block < MAX_PARAM_SPATIAL_SUBFRAMES; block++ ) + { + // Todo OMASA JBM: This might need adjustments + meta_write_index = ( dirac_bs_md_write_idx + block ) % st_ivas->hDirAC->dirac_md_buffer_length; + + for ( b = 0; b < CLDFB_NO_CHANNELS_MAX; b++ ) + { + st_ivas->hDirAC->diffuseness_vector[meta_write_index][b] -= st_ivas->hMasaIsmData->energy_ratio_ism[i][meta_write_index][b]; + } + } + } + for ( block = 0; block < MAX_PARAM_SPATIAL_SUBFRAMES; block++ ) + { + meta_write_index = ( dirac_bs_md_write_idx + block ) % st_ivas->hDirAC->dirac_md_buffer_length; + + for ( b = 0; b < CLDFB_NO_CHANNELS_MAX; b++ ) + { + st_ivas->hDirAC->diffuseness_vector[meta_write_index][b] = max( 0.0f, st_ivas->hDirAC->diffuseness_vector[meta_write_index][b] ); + } + } + } } +#endif + st->next_bit_pos = next_bit_pos_orig; - if ( ivas_format == MASA_FORMAT && st_ivas->nCPE == 1 && st_ivas->hCPE[0]->hStereoDft != NULL && st_ivas->hCPE[0]->hStereoDft->hConfig != NULL ) +#ifdef MASA_AND_OBJECTS + if ( ivas_format == MASA_ISM_FORMAT ) { - st_ivas->hCPE[0]->hStereoDft->hConfig->force_mono_transmission = ivas_total_brate < MASA_STEREO_MIN_BITRATE ? 1 : 0; + int32_t cpe_brate; + cpe_brate = calculate_cpe_brate_MASA_ISM( st_ivas->ism_mode, ivas_total_brate, st_ivas->nchan_ism ); + + if ( st_ivas->nCPE == 1 && st_ivas->hCPE[0]->hStereoDft != NULL && st_ivas->hCPE[0]->hStereoDft->hConfig != NULL ) + { + st_ivas->hCPE[0]->hStereoDft->hConfig->force_mono_transmission = cpe_brate < MASA_STEREO_MIN_BITRATE ? 1 : 0; - if ( ivas_total_brate <= IVAS_SID_5k2 ) + if ( ivas_total_brate <= IVAS_SID_5k2 ) + { + st_ivas->hCPE[0]->hStereoDft->hConfig->force_mono_transmission = 0; + } + } + } + else + { +#endif + if ( ivas_format == MASA_FORMAT && st_ivas->nCPE == 1 && st_ivas->hCPE[0]->hStereoDft != NULL && st_ivas->hCPE[0]->hStereoDft->hConfig != NULL ) { - st_ivas->hCPE[0]->hStereoDft->hConfig->force_mono_transmission = 0; + st_ivas->hCPE[0]->hStereoDft->hConfig->force_mono_transmission = ivas_total_brate < MASA_STEREO_MIN_BITRATE ? 1 : 0; + + if ( ivas_total_brate <= IVAS_SID_5k2 ) + { + st_ivas->hCPE[0]->hStereoDft->hConfig->force_mono_transmission = 0; + } } +#ifdef MASA_AND_OBJECTS } +#endif if ( ivas_format == MASA_FORMAT && st_ivas->nCPE == 1 ) { @@ -317,7 +571,11 @@ ivas_error ivas_masa_decode( } } +#ifdef OMASA_EXT_OUTPUT + if ( ( st_ivas->ivas_format == MASA_FORMAT || st_ivas->ivas_format == MASA_ISM_FORMAT ) && st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_EXTERNAL ) +#else if ( st_ivas->ivas_format == MASA_FORMAT && st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_EXTERNAL ) +#endif { create_masa_ext_out_meta( hMasa, hQMetaData, st_ivas->nchan_transport ); } @@ -338,6 +596,10 @@ ivas_error ivas_masa_dec_open( { MASA_DECODER_HANDLE hMasa; ivas_error error; +#ifdef MASA_AND_OBJECTS + int16_t i; + int32_t ism_total_brate; +#endif error = IVAS_ERR_OK; @@ -346,7 +608,23 @@ ivas_error ivas_masa_dec_open( return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) ); } - ivas_masa_set_elements( st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->mc_mode, st_ivas->nchan_transport, st_ivas->hQMetaData, &st_ivas->element_mode_init, &st_ivas->nSCE, &st_ivas->nCPE ); +#ifdef MASA_AND_OBJECTS + ism_total_brate = 0; + if ( st_ivas->ivas_format == MASA_ISM_FORMAT && st_ivas->nSCE > 0 && ( st_ivas->ism_mode == ISM_MASA_MODE_DISC || st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) ) + { + for ( i = 0; i < st_ivas->nSCE; i++ ) + { + ism_total_brate += st_ivas->hSCE[i]->element_brate; + } + } +#endif + + ivas_masa_set_elements( st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->mc_mode, st_ivas->nchan_transport, st_ivas->hQMetaData, &st_ivas->element_mode_init, &st_ivas->nSCE, &st_ivas->nCPE +#ifdef MASA_AND_OBJECTS + , + st_ivas->ivas_format, st_ivas->ism_mode, ism_total_brate +#endif + ); mvs2s( DirAC_block_grouping, hMasa->config.block_grouping, MAX_PARAM_SPATIAL_SUBFRAMES + 1 ); mvs2s( MASA_band_grouping_24, hMasa->config.band_grouping, MASA_FREQUENCY_BANDS + 1 ); @@ -487,15 +765,43 @@ static ivas_error ivas_masa_dec_config( uint8_t maxBand; int16_t maxBin; ivas_error error; - +#ifdef MASA_AND_OBJECTS + int32_t ivas_total_brate; + int32_t ism_total_brate; +#endif error = IVAS_ERR_OK; hMasa = st_ivas->hMasa; - ivas_masa_set_elements( st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->mc_mode, st_ivas->nchan_transport, st_ivas->hQMetaData, &st_ivas->element_mode_init, &st_ivas->nSCE, &st_ivas->nCPE ); +#ifdef MASA_AND_OBJECTS + ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; + ism_total_brate = 0; + if ( st_ivas->ivas_format == MASA_ISM_FORMAT && st_ivas->nSCE > 0 && ( st_ivas->ism_mode == ISM_MASA_MODE_DISC || st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) ) + { + for ( i = 0; i < st_ivas->nSCE; i++ ) + { + ism_total_brate += st_ivas->hSCE[i]->element_brate; + } + } - ivas_masa_set_coding_config( &( hMasa->config ), hMasa->data.band_mapping, st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->nchan_transport, ( st_ivas->ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCMASA ) ); + ivas_masa_set_elements( ivas_total_brate, st_ivas->mc_mode, st_ivas->nchan_transport, st_ivas->hQMetaData, &st_ivas->element_mode_init, &st_ivas->nSCE, &st_ivas->nCPE, st_ivas->ivas_format, st_ivas->ism_mode, ism_total_brate ); - if ( st_ivas->ivas_format == MASA_FORMAT && st_ivas->hDecoderConfig->ivas_total_brate == IVAS_512k ) + if ( st_ivas->ivas_format == MASA_ISM_FORMAT ) + { + ivas_masa_set_coding_config( &( hMasa->config ), hMasa->data.band_mapping, st_ivas->hCPE[0]->element_brate, st_ivas->nchan_transport, MC_MODE_NONE ); + } + else + { + ivas_masa_set_coding_config( &( hMasa->config ), hMasa->data.band_mapping, st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->nchan_transport, ( st_ivas->ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCMASA ) ); + } +#else + ivas_masa_set_elements( st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->mc_mode, st_ivas->nchan_transport, st_ivas->hQMetaData, &st_ivas->element_mode_init, &st_ivas->nSCE, &st_ivas->nCPE ); + ivas_masa_set_coding_config( &( hMasa->config ), hMasa->data.band_mapping, st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->nchan_transport, ( st_ivas->ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCMASA ) ); +#endif +#ifdef MASA_AND_OBJECTS + if ( ( st_ivas->ivas_format == MASA_FORMAT || st_ivas->ivas_format == MASA_ISM_FORMAT ) && st_ivas->hDecoderConfig->ivas_total_brate == IVAS_512k ) +#else + if ( ( st_ivas->ivas_format == MASA_FORMAT ) && st_ivas->hDecoderConfig->ivas_total_brate == IVAS_512k ) +#endif { hMasa->config.mergeRatiosOverSubframes = 0; /* initialize spherical grid */ @@ -971,6 +1277,9 @@ ivas_error ivas_masa_dec_reconfigure( int32_t ivas_total_brate, last_ivas_total_brate; int16_t numCldfbAnalyses_old, numCldfbSyntheses_old; ivas_error error; +#ifdef MASA_AND_OBJECTS + int32_t ism_total_brate; +#endif error = IVAS_ERR_OK; @@ -982,7 +1291,11 @@ ivas_error ivas_masa_dec_reconfigure( /* renderer might have changed, reselect */ ivas_renderer_select( st_ivas ); - if ( ( st_ivas->renderer_type == RENDERER_DIRAC && st_ivas->hDirACRend == NULL ) || ( ( st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) && st_ivas->hDiracDecBin == NULL ) ) +#ifdef OMASA_BRSW_MONO_FIX + if ( ( st_ivas->renderer_type != RENDERER_DISABLE && st_ivas->renderer_type != RENDERER_MONO_DOWNMIX ) && st_ivas->hDirAC == NULL ) +#else + if ( st_ivas->renderer_type != RENDERER_DISABLE && st_ivas->hDirAC == NULL ) +#endif { /* init a new DirAC dec */ if ( ( error = ivas_dirac_dec_config( st_ivas, DIRAC_OPEN ) ) != IVAS_ERR_OK ) @@ -990,16 +1303,14 @@ ivas_error ivas_masa_dec_reconfigure( return error; } } - else if ( st_ivas->renderer_type == RENDERER_DISABLE ) +#ifdef OMASA_BRSW_MONO_FIX + else if ( ( st_ivas->renderer_type == RENDERER_DISABLE || st_ivas->renderer_type == RENDERER_MONO_DOWNMIX ) && st_ivas->hDirAC != NULL ) +#else + else if ( st_ivas->renderer_type == RENDERER_DISABLE && st_ivas->hDirAC != NULL ) +#endif { - if ( st_ivas->hDirAC != NULL ) - { - /* close all unnecessary parametric decoding and rendering */ - ivas_dirac_dec_close_binaural_data( &st_ivas->hDiracDecBin ); - ivas_dirac_rend_close( &( st_ivas->hDirACRend ) ); - ivas_spat_hSpatParamRendCom_close( &( st_ivas->hSpatParamRendCom ) ); - ivas_dirac_dec_close( &( st_ivas->hDirAC ) ); - } + /* close unnecessary DirAC dec */ + ivas_dirac_dec_close( &( st_ivas->hDirAC ) ); } /* possible reconfigure is done later */ @@ -1018,14 +1329,6 @@ ivas_error ivas_masa_dec_reconfigure( sts = st_ivas->hSCE[sce_id]->hCoreCoder; sts[0]->bit_stream = bit_stream + num_bits; num_bits += (int16_t) ( st_ivas->hSCE[sce_id]->element_brate / FRAMES_PER_SEC ); - - if ( ( st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) && st_ivas->hDiracDecBin != NULL ) - { - if ( ( error = ivas_dirac_dec_config( st_ivas, DIRAC_RECONFIGURE ) ) != IVAS_ERR_OK ) - { - return error; - } - } } for ( cpe_id = 0; cpe_id < st_ivas->nCPE; cpe_id++ ) @@ -1040,13 +1343,13 @@ ivas_error ivas_masa_dec_reconfigure( sts = st_ivas->hCPE[cpe_id]->hCoreCoder; sts[0]->bit_stream = bit_stream + num_bits; num_bits += (int16_t) ( st_ivas->hCPE[cpe_id]->element_brate / FRAMES_PER_SEC ); - + /* Todo: Nokia make for MASA_ISM*/ if ( ( ivas_total_brate < MASA_STEREO_MIN_BITRATE && last_ivas_total_brate >= MASA_STEREO_MIN_BITRATE ) || ( ivas_total_brate < MASA_STEREO_MIN_BITRATE && last_ivas_total_brate == FRAME_NO_DATA ) ) { st_ivas->hCPE[cpe_id]->nchan_out = 1; - if ( ( st_ivas->renderer_type == RENDERER_DIRAC && st_ivas->hDirACRend != NULL ) || ( ( st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) && st_ivas->hDiracDecBin != NULL ) ) + if ( st_ivas->hDirAC != NULL ) { if ( ( error = ivas_dirac_dec_config( st_ivas, DIRAC_RECONFIGURE ) ) != IVAS_ERR_OK ) { @@ -1058,7 +1361,7 @@ ivas_error ivas_masa_dec_reconfigure( { st_ivas->hCPE[cpe_id]->nchan_out = CPE_CHANNELS; - if ( ( st_ivas->renderer_type == RENDERER_DIRAC && st_ivas->hDirACRend != NULL ) || ( ( st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) && st_ivas->hDiracDecBin != NULL ) ) + if ( st_ivas->hDirAC != NULL ) { if ( ( error = ivas_dirac_dec_config( st_ivas, DIRAC_RECONFIGURE ) ) != IVAS_ERR_OK ) { @@ -1067,27 +1370,69 @@ ivas_error ivas_masa_dec_reconfigure( } } } - if ( st_ivas->hDiracDecBin != NULL ) { /* regularization factor is bitrate-dependent */ st_ivas->hDiracDecBin->reqularizationFactor = configure_reqularization_factor( st_ivas->ivas_format, st_ivas->hDecoderConfig->ivas_total_brate ); } - /*-----------------------------------------------------------------* - * CLDFB instances - *-----------------------------------------------------------------*/ +#ifdef MASA_AND_OBJECTS + if ( st_ivas->ivas_format == MASA_FORMAT && st_ivas->last_ivas_format == MASA_FORMAT ) /* note: switching within OMASA is handled in ivas_omasa_dec_config() */ + { +#endif + /*-----------------------------------------------------------------* + * TD Decorrelator + *-----------------------------------------------------------------*/ + + if ( st_ivas->hDiracDecBin != NULL ) + { + if ( ( error = ivas_td_decorr_reconfig_dec( st_ivas->ivas_format, st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->nchan_transport, st_ivas->hDecoderConfig->output_Fs, &( st_ivas->hDiracDecBin->hTdDecorr ), &( st_ivas->hDiracDecBin->useTdDecorr ) ) ) != IVAS_ERR_OK ) + { + return error; + } + } - if ( ( error = ivas_cldfb_dec_reconfig( st_ivas, st_ivas->nchan_transport, numCldfbAnalyses_old, numCldfbSyntheses_old ) ) != IVAS_ERR_OK ) + /*-----------------------------------------------------------------* + * CLDFB instances + *-----------------------------------------------------------------*/ + + if ( ( error = ivas_cldfb_dec_reconfig( st_ivas, st_ivas->nchan_transport, numCldfbAnalyses_old, numCldfbSyntheses_old ) ) != IVAS_ERR_OK ) + { + return error; + } + + /*-----------------------------------------------------------------* + * Set-up MASA coding elements and bitrates + *-----------------------------------------------------------------*/ +#ifdef MASA_AND_OBJECTS + } +#endif + +#ifdef MASA_AND_OBJECTS + ism_total_brate = 0; + if ( st_ivas->ivas_format == MASA_ISM_FORMAT && st_ivas->nSCE > 0 && ( st_ivas->ism_mode == ISM_MASA_MODE_DISC || st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) ) { - return error; + for ( n = 0; n < st_ivas->nSCE; n++ ) + { + ism_total_brate += st_ivas->hSCE[n]->element_brate; + } } +#endif - /*-----------------------------------------------------------------* - * Set-up MASA coding elements and bitrates - *-----------------------------------------------------------------*/ + ivas_masa_set_elements( ivas_total_brate, st_ivas->mc_mode, st_ivas->nchan_transport, st_ivas->hQMetaData, &tmp, &tmp, &tmp +#ifdef MASA_AND_OBJECTS + , + st_ivas->ivas_format, st_ivas->ism_mode, ism_total_brate +#endif + ); - ivas_masa_set_elements( ivas_total_brate, st_ivas->mc_mode, st_ivas->nchan_transport, st_ivas->hQMetaData, &tmp, &tmp, &tmp ); +#ifdef MASA_AND_OBJECTS + if ( st_ivas->ivas_format == MASA_FORMAT ) + { + st_ivas->nchan_ism = 0; + st_ivas->ism_mode = ISM_MODE_NONE; + } +#endif if ( st_ivas->hDecoderConfig->voip_active == 1 ) { @@ -1117,6 +1462,12 @@ ivas_error ivas_masa_dec_reconfigure( } +/*-------------------------------------------------------------------* + * ivas_spar_param_to_masa_param_mapping() + * + * Determine MASA metadata from the SPAR metadata + *-------------------------------------------------------------------*/ + void ivas_spar_param_to_masa_param_mapping( Decoder_Struct *st_ivas, /* i/o: IVAS decoder struct */ float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* i : Input audio in CLDFB domain, real */ @@ -1143,17 +1494,18 @@ void ivas_spar_param_to_masa_param_mapping( int16_t slot_idx, slot_idx_start, sf; SPAR_DEC_HANDLE hSpar; float slot_fac; - SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom; /* Set values */ hDirAC = st_ivas->hDirAC; - hSpatParamRendCom = st_ivas->hSpatParamRendCom; - hSpatParamRendCom->numSimultaneousDirections = 1; - hDiffuseDist = st_ivas->hDiracDecBin->hDiffuseDist; +#ifdef MASA_AND_OBJECTS + hDirAC->numParametricDirections = 1; +#endif + hDirAC->numSimultaneousDirections = 1; + hDiffuseDist = st_ivas->hDirAC->hDiffuseDist; nchan_transport = st_ivas->nchan_transport; band_grouping = hDirAC->band_grouping; hSpar = st_ivas->hSpar; - dirac_write_idx = hSpatParamRendCom->render_to_md_map[subframe]; + dirac_write_idx = hDirAC->render_to_md_map[subframe]; /* Init arrays */ for ( i = 0; i < FOA_CHANNELS; i++ ) @@ -1238,7 +1590,7 @@ void ivas_spar_param_to_masa_param_mapping( set_zero( transportSignalEnergies[1], nBins ); set_zero( transportSignalCrossCorrelation, nBins ); - for ( slot = 0; slot < hSpatParamRendCom->subframe_nbslots[subframe]; slot++ ) + for ( slot = 0; slot < hDirAC->subframe_nbslots[subframe]; slot++ ) { for ( bin = 0; bin < nBins; bin++ ) { @@ -1298,13 +1650,13 @@ void ivas_spar_param_to_masa_param_mapping( ratio = I / fmaxf( 1e-12f, E ); /* Energy ratio */ ratio = fmaxf( 0.0f, fminf( 1.0f, ratio ) ); - hSpatParamRendCom->azimuth[dirac_write_idx][bin] = (int16_t) roundf( azi / PI_OVER_180 ); - hSpatParamRendCom->elevation[dirac_write_idx][bin] = (int16_t) roundf( ele / PI_OVER_180 ); - hSpatParamRendCom->energy_ratio1[dirac_write_idx][bin] = ratio; - hSpatParamRendCom->diffuseness_vector[dirac_write_idx][bin] = 1.0f - ratio; + hDirAC->azimuth[dirac_write_idx][bin] = (int16_t) roundf( azi / PI_OVER_180 ); + hDirAC->elevation[dirac_write_idx][bin] = (int16_t) roundf( ele / PI_OVER_180 ); + hDirAC->energy_ratio1[dirac_write_idx][bin] = ratio; + hDirAC->diffuseness_vector[dirac_write_idx][bin] = 1.0f - ratio; - hSpatParamRendCom->spreadCoherence[dirac_write_idx][bin] = 0.0f; - hSpatParamRendCom->surroundingCoherence[dirac_write_idx][bin] = 0.0f; + hDirAC->spreadCoherence[dirac_write_idx][bin] = 0.0f; + hDirAC->surroundingCoherence[dirac_write_idx][bin] = 0.0f; /* Determine directional distribution of the indirect audio based on the SPAR mixing matrices (and the transport audio signals when 2 TC) */ if ( hDiffuseDist != NULL ) @@ -1519,3 +1871,622 @@ static void create_masa_ext_out_meta( return; } + +#ifdef MASA_AND_OBJECTS +// Todo OMASA JBM: There is a lot of metadata access here via dirac indices, they could be wrong post JBM. +static void decode_index_slice( + int16_t index, /* i : index to decode */ + int16_t *ratio_idx_ism, /* o : decodec array of integers */ + const int16_t nchan_ism, /* i : number of elements in array (objects) */ + const int16_t K ) /* i : sum of array elements */ +{ + int16_t i, j, sum, elem; + int16_t base[MAX_NUM_OBJECTS]; + + switch ( nchan_ism ) + { + case 2: + ratio_idx_ism[0] = index; + ratio_idx_ism[1] = K - ratio_idx_ism[0]; + break; + case 3: + case 4: + { + j = 0; + while ( index >= 0 ) + { + if ( valid_ratio_index( j, K, nchan_ism - 1 ) ) + { + index--; + } + j++; + } + j--; + base[0] = 1; + for ( i = 1; i < nchan_ism - 1; i++ ) + { + base[i] = base[i - 1] * 10; + } + sum = 0; + for ( i = nchan_ism - 2; i >= 0; i-- ) + { + elem = j / base[i]; + ratio_idx_ism[nchan_ism - i - 2] = elem; + sum += elem; + j -= elem * base[i]; + } + ratio_idx_ism[nchan_ism - 1] = K - sum; + } + + default: + break; + } + + return; +} + + +static void read_ism_ratio_index( + int16_t ratio_ism_idx[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS], /* o : ISM read ratio indexes */ + const int16_t nchan_ism, /* i : number of objects */ + const int16_t numCodingBands, /* i : number of subbands */ + const int16_t sf, /* i : index of subframe */ + int16_t ratio_ism_idx_prev_sf[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS], /* i : previous subframe ISM ratio indexes */ + uint16_t *bit_stream, /* i : bitstream */ + int16_t *next_bit_pos, /* i/o: position in bitstream */ + float *masa_to_total_energy_ratio, /* i : masa to total ratios */ + const int16_t idx_sep_obj, /* i : index of separated index, -1 if none */ + int16_t *num_zeros /* i/o: number of zero values in first subframe for separated object */ +) +{ + int16_t b, i, b_signif; + int16_t index; + int16_t GR_order, differential_subframe; + int16_t buf; + int16_t no_levels_ratio_ism; + int16_t bits_index; + int16_t ratio_ism_idx_ref[MAX_NUM_OBJECTS]; + int16_t idx_sep_obj_local, shift_one; + + idx_sep_obj_local = idx_sep_obj; + if ( idx_sep_obj > -1 ) + { + if ( idx_sep_obj == nchan_ism - 1 && nchan_ism > 2 ) + { + idx_sep_obj_local = 0; + } + } + + b_signif = 0; + no_levels_ratio_ism = ( ( 1 << PARAM_ISM_POW_RATIO_NBITS ) - 1 ); + while ( ( b_signif < numCodingBands ) && ( masa_to_total_energy_ratio[b_signif] >= MASA2TOTAL_THR ) ) + { + /* distribute evenly the objects */ + distribute_evenly_ism( ratio_ism_idx[b_signif], no_levels_ratio_ism, nchan_ism ); + b_signif++; + } + + if ( b_signif == numCodingBands ) + { + return; + } + else + { + + if ( sf == 0 ) + { + bits_index = bits_index_ism_ratio( nchan_ism ); + + /* read coding type */ + if ( bit_stream[( *next_bit_pos )--] == 1 ) + { + /* independent coding*/ + for ( b = 0; b < numCodingBands; b++ ) + { + if ( masa_to_total_energy_ratio[b] < MASA2TOTAL_THR ) + { + index = 0; + for ( i = 0; i < bits_index; i++ ) + { + index = ( index << 1 ) + bit_stream[( *next_bit_pos )--]; + } + decode_index_slice( index, ratio_ism_idx[b], nchan_ism, no_levels_ratio_ism ); + if ( idx_sep_obj > -1 && ratio_ism_idx[b][idx_sep_obj_local] == 0 ) + { + ( *num_zeros )++; + } + } + else + { + /* distribute evenly the objects */ + distribute_evenly_ism( ratio_ism_idx[b], no_levels_ratio_ism, nchan_ism ); + } + } + } + else + { + /* differential coding */ + index = 0; + for ( i = 0; i < bits_index; i++ ) + { + index = ( index << 1 ) + bit_stream[( *next_bit_pos )--]; + } + decode_index_slice( index, ratio_ism_idx[b_signif], nchan_ism, no_levels_ratio_ism ); + if ( idx_sep_obj > -1 && ratio_ism_idx[b_signif][idx_sep_obj_local] == 0 ) + { + ( *num_zeros )++; + } + mvs2s( ratio_ism_idx[b_signif], ratio_ism_idx_ref, nchan_ism ); + for ( b = b_signif + 1; b < numCodingBands; b++ ) + { + if ( masa_to_total_energy_ratio[b] < MASA2TOTAL_THR ) + { + ratio_ism_idx[b][nchan_ism - 1] = no_levels_ratio_ism; + for ( i = 0; i < nchan_ism - 1; i++ ) + { + buf = ivas_qmetadata_DecodeExtendedGR( bit_stream, next_bit_pos, 100, 0 ); + if ( ( buf % 2 ) == 0 ) + { + ratio_ism_idx[b][i] = -( buf >> 1 ); + } + else + { + ratio_ism_idx[b][i] = ( ( buf + 1 ) >> 1 ); + } + ratio_ism_idx[b][i] = ratio_ism_idx[b][i] + ratio_ism_idx_ref[i]; + ratio_ism_idx[b][nchan_ism - 1] -= ratio_ism_idx[b][i]; + } + mvs2s( ratio_ism_idx[b], ratio_ism_idx_ref, nchan_ism ); + if ( idx_sep_obj > -1 && ratio_ism_idx[b][idx_sep_obj_local] == 0 ) + { + ( *num_zeros )++; + } + } + else + { + /* distribute evenly the objects */ + distribute_evenly_ism( ratio_ism_idx[b], no_levels_ratio_ism, nchan_ism ); + } + } + } + } + else + { + if ( numCodingBands > 1 ) + { + /* read prediction type */ + differential_subframe = bit_stream[( *next_bit_pos )--]; + } + else + { + differential_subframe = 1; + } + + if ( *num_zeros == numCodingBands ) + { + shift_one = 1; + } + else + { + shift_one = 0; + } + + if ( shift_one == 1 && nchan_ism == 2 ) + { + /* nothing has been sent ; values can be inferred */ + for ( b = b_signif; b < numCodingBands; b++ ) + { + if ( masa_to_total_energy_ratio[b] < MASA2TOTAL_THR ) + { + if ( idx_sep_obj_local == 0 ) + { + ratio_ism_idx[b][0] = 0; + ratio_ism_idx[b][1] = 7; + } + else + { + ratio_ism_idx[b][0] = 7; + ratio_ism_idx[b][1] = 0; + } + } + } + } + else + { + /* read GR order */ + GR_order = bit_stream[( *next_bit_pos )--]; + for ( b = b_signif; b < numCodingBands; b++ ) + { + if ( masa_to_total_energy_ratio[b] < MASA2TOTAL_THR ) + { + for ( i = 0; i < nchan_ism - 1 - shift_one; i++ ) + { + buf = ivas_qmetadata_DecodeExtendedGR( bit_stream, next_bit_pos, 100, GR_order ); + if ( ( buf % 2 ) == 0 ) + { + ratio_ism_idx[b][i] = -( buf >> 1 ); + } + else + { + ratio_ism_idx[b][i] = ( ( buf + 1 ) >> 1 ); + } + } + + /* insert separated obj */ + if ( shift_one ) + { + for ( i = nchan_ism - 1; i > idx_sep_obj_local; i-- ) + { + ratio_ism_idx[b][i] = ratio_ism_idx[b][i - 1]; + } + ratio_ism_idx[b][idx_sep_obj_local] = 0; /* this is only difference; need to pdate later as well */ + } + } + } + if ( differential_subframe ) + { + /* differential to previous subframe */ + for ( b = b_signif; b < numCodingBands; b++ ) + { + if ( masa_to_total_energy_ratio[b] < MASA2TOTAL_THR ) + { + ratio_ism_idx[b][nchan_ism - 1] = no_levels_ratio_ism; + for ( i = 0; i < nchan_ism - 1; i++ ) + { + ratio_ism_idx[b][i] = ratio_ism_idx[b][i] + ratio_ism_idx_prev_sf[b][i]; + if ( shift_one && i == idx_sep_obj_local ) + { + ratio_ism_idx[b][i] = 0; + } + ratio_ism_idx[b][nchan_ism - 1] -= ratio_ism_idx[b][i]; + } + } + else + { + /* distribute evenly the objects */ + distribute_evenly_ism( ratio_ism_idx[b], no_levels_ratio_ism, nchan_ism ); + } + } + } + else + { + /* difference to previous subband */ + ratio_ism_idx[b_signif][nchan_ism - 1] = no_levels_ratio_ism; + + /* first significant subband - differential to previous subframe */ + for ( i = 0; i < nchan_ism - 1; i++ ) + { + ratio_ism_idx[b_signif][i] = ratio_ism_idx[b_signif][i] + ratio_ism_idx_prev_sf[b_signif][i]; + if ( shift_one && i == idx_sep_obj_local ) + { + ratio_ism_idx[b_signif][i] = 0; + } + ratio_ism_idx[b_signif][nchan_ism - 1] -= ratio_ism_idx[b_signif][i]; + } + + /* rest of subbands differential to previous subband */ + mvs2s( ratio_ism_idx[b_signif], ratio_ism_idx_ref, nchan_ism ); + for ( b = b_signif + 1; b < numCodingBands; b++ ) + { + if ( masa_to_total_energy_ratio[b] < MASA2TOTAL_THR ) + { + ratio_ism_idx[b][nchan_ism - 1] = no_levels_ratio_ism; + for ( i = 0; i < nchan_ism - 1; i++ ) + { + ratio_ism_idx[b][i] = ratio_ism_idx[b][i] + ratio_ism_idx_ref[i]; + if ( shift_one && i == idx_sep_obj_local ) + { + ratio_ism_idx[b][i] = 0; + } + ratio_ism_idx[b][nchan_ism - 1] -= ratio_ism_idx[b][i]; + } + mvs2s( ratio_ism_idx[b], ratio_ism_idx_ref, nchan_ism ); + } + else + { + /* distribute evenly the objects */ + distribute_evenly_ism( ratio_ism_idx[b], no_levels_ratio_ism, nchan_ism ); + } + } + } + } + } + + return; + } +} + + +static void decode_ism_ratios( + uint16_t *bit_stream, /* i : bitstream */ + int16_t *next_bit_pos, /* i/o: position in bitstream */ + IVAS_QMETADATA_HANDLE hQMetaData, /* i : Metadata handle */ + float ratio_ism[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS], /* o : ISM ratios */ + const int16_t n_ism, /* i : number of objects */ + const int16_t nbands, /* i : number of subbands */ + const int16_t numSf, /* i : number of subframes */ + const int16_t idx_separated_object /* i: index of separated object */ +) +{ + int16_t sf, band; + int16_t ratio_ism_idx[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS]; + int16_t ratio_ism_idx_prev_sf[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS]; + float tmp; + int16_t num_zeros; + num_zeros = 0; + + /* hQMetaData->q_direction->cfg.nblocks; */ + for ( sf = 0; sf < numSf; sf++ ) + { + /* read ism ratio indexes */ + read_ism_ratio_index( ratio_ism_idx, n_ism, nbands, sf, ratio_ism_idx_prev_sf, bit_stream, next_bit_pos, hQMetaData->masa_to_total_energy_ratio[sf], idx_separated_object, &num_zeros ); + + /* save previous subframe index values */ + if ( sf < numSf - 1 ) + { + /* Todo Nokia: can be moved to the read_ism_ratio ... function */ + for ( band = 0; band < nbands; band++ ) + { + mvs2s( ratio_ism_idx[band], ratio_ism_idx_prev_sf[band], n_ism ); + } + } + + /* reconstructed values */ + for ( band = 0; band < nbands; band++ ) + { + reconstruct_ism_ratios( ratio_ism_idx[band], n_ism, 1.0f / (float) ( ( 1 << PARAM_ISM_POW_RATIO_NBITS ) - 1 ), ratio_ism[sf][band] ); + } + + if ( ( n_ism > 2 ) && ( idx_separated_object == n_ism - 1 ) ) + { + /* rotate */ + for ( band = 0; band < nbands; band++ ) + { + if ( hQMetaData->masa_to_total_energy_ratio[sf][band] < MASA2TOTAL_THR ) + { + tmp = ratio_ism[sf][band][n_ism - 1]; + ratio_ism[sf][band][n_ism - 1] = ratio_ism[sf][band][0]; + ratio_ism[sf][band][0] = tmp; + } + } + } + + if ( nbands == 1 ) + { + for ( band = 1; band < 5; band++ ) + { + mvr2r( ratio_ism[sf][0], ratio_ism[sf][band], n_ism ); + } + } + } + + if ( numSf == 1 ) + { + for ( sf = 1; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ ) + { + for ( band = 0; band < nbands; band++ ) + { + mvr2r( ratio_ism[0][band], ratio_ism[sf][band], n_ism ); + } + } + } + + return; +} + + +static int16_t ivas_decode_masaism_metadata( + IVAS_QMETADATA_HANDLE hQMetaData, + MASA_DECODER_HANDLE hMasa, + MASA_ISM_DATA_HANDLE hMasaIsmData, + const int16_t nchan_ism, + uint16_t *bit_stream, + int16_t *next_bit_pos, + const int16_t idx_separated_object, + const int16_t ism_imp, + const int16_t dirac_bs_md_write_idx, + const int16_t dirac_md_buffer_length ) +{ + int16_t sf, band, dir, nbands, nblocks, obj, i; + float energy_ratio_ism[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS]; + int16_t *band_mapping; + int16_t b; + int16_t bits_ism[MAX_NUM_OBJECTS], index; + uint16_t idx_el, idx_az; + float azimuth, elevation; + int16_t nb_bits_read; + float delta_phi; + int16_t meta_write_index; + + nb_bits_read = *next_bit_pos; + nbands = hQMetaData->q_direction->cfg.nbands; + nblocks = hQMetaData->q_direction->cfg.nblocks; /* To do: what if other value than 4? */ + + /* Read MASA-to-total energy ratios */ + decode_masa_to_total( bit_stream, next_bit_pos, hQMetaData->masa_to_total_energy_ratio, nbands, nblocks ); + if ( nchan_ism > 1 ) + { + /* read ISM ratios */ + decode_ism_ratios( bit_stream, next_bit_pos, hQMetaData, energy_ratio_ism, nchan_ism, nbands, nblocks, idx_separated_object ); + } + else + { + for ( sf = 0; sf < nblocks; sf++ ) + { + for ( band = 0; band < nbands; band++ ) + { + energy_ratio_ism[sf][band][0] = 1.0f; + } + } + } + + /* read ISM metadata */ + calculate_nbits_meta( nchan_ism, energy_ratio_ism, hQMetaData->masa_to_total_energy_ratio, nblocks, nbands, bits_ism, idx_separated_object, ism_imp ); + + for ( obj = 0; obj < nchan_ism; obj++ ) + { + index = 0; + if ( bits_ism[obj] < 8 ) /* if low resolution, can look to the past */ + { + /* read if same as previous */ + if ( bit_stream[( *next_bit_pos )--] ) + { + azimuth = hMasaIsmData->q_azimuth_old[obj]; + elevation = hMasaIsmData->q_elevation_old[obj]; + } + else + { + for ( i = 0; i < bits_ism[obj]; i++ ) + { + index = ( index << 1 ) + bit_stream[( *next_bit_pos )--]; + } + deindex_spherical_component( index, &azimuth, &elevation, &idx_az, &idx_el, bits_ism[obj], MC_LS_SETUP_INVALID ); + + if ( azimuth * hMasaIsmData->q_azimuth_old[obj] > 0 ) + { + delta_phi = 180.0f / (float) ( no_phi_masa[bits_ism[obj] - 1][idx_el] ); /* 360/2*/ + if ( azimuth - hMasaIsmData->q_azimuth_old[obj] > delta_phi ) + { + azimuth -= delta_phi; + } + else + { + if ( hMasaIsmData->q_azimuth_old[obj] - azimuth > delta_phi ) + { + azimuth += delta_phi; + } + } + } + + hMasaIsmData->q_azimuth_old[obj] = azimuth; + hMasaIsmData->q_elevation_old[obj] = elevation; + } + } + else + { + for ( i = 0; i < bits_ism[obj]; i++ ) + { + index = ( index << 1 ) + bit_stream[( *next_bit_pos )--]; + } + deindex_spherical_component( index, &azimuth, &elevation, &idx_az, &idx_el, bits_ism[obj], MC_LS_SETUP_INVALID ); + hMasaIsmData->q_azimuth_old[obj] = azimuth; + hMasaIsmData->q_elevation_old[obj] = elevation; + } + + for ( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ ) + { + meta_write_index = ( dirac_bs_md_write_idx + sf ) % dirac_md_buffer_length; + hMasaIsmData->azimuth_ism[obj][meta_write_index] = (int16_t) rint( azimuth ); + hMasaIsmData->elevation_ism[obj][meta_write_index] = (int16_t) rint( elevation ); + } + } + + /* Modify ISM metadata based on the MASA-to-total energy ratios */ + for ( sf = 0; sf < nblocks; sf++ ) + { + for ( band = 0; band < nbands; band++ ) + { + for ( dir = 0; dir < nchan_ism; dir++ ) + { + energy_ratio_ism[sf][band][dir] *= ( 1.0f - hQMetaData->masa_to_total_energy_ratio[sf][band] ); + } + } + } + + /* Set data to struct in bins */ + band_mapping = hMasa->data.band_mapping; + for ( band = 0; band < hMasa->config.numCodingBands; ++band ) + { + for ( b = MASA_band_grouping_24[band_mapping[band]]; b < MASA_band_grouping_24[band_mapping[band + 1]]; ++b ) + { + for ( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; ++sf ) + { + if ( nblocks == 1 ) + { + i = 0; + } + else + { + i = sf; + } + + meta_write_index = ( dirac_bs_md_write_idx + sf ) % dirac_md_buffer_length; + + for ( dir = 0; dir < nchan_ism; dir++ ) + { + hMasaIsmData->energy_ratio_ism[dir][meta_write_index][b] = energy_ratio_ism[i][band][dir]; + } + } + } + } + + return ( nb_bits_read - *next_bit_pos ); +} + + +/*-------------------------------------------------------------------* + * ivas_masa_ism_set_edited_objects() + * + * + *-------------------------------------------------------------------*/ + +void ivas_masa_ism_set_edited_objects( + Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ +) +{ + int16_t dir, sf; + MASA_ISM_DATA_HANDLE hMasaIsmData; + + hMasaIsmData = st_ivas->hMasaIsmData; + + /* Set positions of the edited objects */ + if ( st_ivas->ism_mode == ISM_MASA_MODE_DISC ) + { + if ( st_ivas->editing_ism_enabled ) + { + for ( sf = 0; sf < ( MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR ); sf++ ) + { + hMasaIsmData->azimuth_ism[st_ivas->index_of_edited_ism][sf] = st_ivas->azimuth_edited; + hMasaIsmData->elevation_ism[st_ivas->index_of_edited_ism][sf] = st_ivas->elevation_edited; + } + + st_ivas->hIsmMetaData[st_ivas->index_of_edited_ism]->azimuth = st_ivas->azimuth_edited; + st_ivas->hIsmMetaData[st_ivas->index_of_edited_ism]->elevation = st_ivas->elevation_edited; + } + } + else if ( st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) + { + /* Directions cannot be edited in this mode */ + } + else + { + for ( dir = 0; dir < MAX_NUM_OBJECTS; dir++ ) + { + if ( dir == st_ivas->index_of_edited_ism && st_ivas->editing_ism_enabled ) + { + hMasaIsmData->ism_is_edited[dir] = 1; + hMasaIsmData->azimuth_ism_edited[dir] = st_ivas->azimuth_edited; + hMasaIsmData->elevation_ism_edited[dir] = st_ivas->elevation_edited; + } + else + { + hMasaIsmData->ism_is_edited[dir] = 0; + } + } + + if ( st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ && st_ivas->editing_ism_enabled ) + { + if ( st_ivas->hMasaIsmData->idx_separated_ism == st_ivas->index_of_edited_ism ) + { + for ( sf = 0; sf < ( MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR ); sf++ ) + { + st_ivas->hMasaIsmData->azimuth_separated_ism[sf] = st_ivas->azimuth_edited; + st_ivas->hMasaIsmData->elevation_separated_ism[sf] = st_ivas->elevation_edited; + } + } + } + } + + return; +} +#endif diff --git a/lib_dec/ivas_mc_param_dec.c b/lib_dec/ivas_mc_param_dec.c index 0ba001d415aee165d188879bcfa20bf787f76ae0..8f750fa819bf5cff7cd551e6fa01f2eaba3c438c 100644 --- a/lib_dec/ivas_mc_param_dec.c +++ b/lib_dec/ivas_mc_param_dec.c @@ -3090,13 +3090,19 @@ static void ivas_param_mc_bs_decode_parameter_values( int16_t i, j, k; float dequant_seq[PARAM_MC_MAX_PARAMETER_BANDS * PARAM_MC_MAX_VAL_MAP_SIZE]; float dequant_ordered[PARAM_MC_MAX_PARAMETER_BANDS * PARAM_MC_MAX_VAL_MAP_SIZE]; +#ifdef FIX_578_PARAMMC_ILD_BS int16_t n_lfe_idx; +#endif range_coding = bit_buffer[( *bit_pos )++]; /* Decoding the sequence */ +#ifdef FIX_578_PARAMMC_ILD_BS n_lfe_idx = map_size - map_size_wo_lfe; sz_seq = num_param_bands * ( map_size_wo_lfe ) + num_lfe_bands * n_lfe_idx; +#else + sz_seq = num_param_bands * ( map_size_wo_lfe ) + num_lfe_bands; +#endif set_s( idx, 0, PARAM_MC_MAX_PARAMETER_BANDS * PARAM_MC_MAX_VAL_MAP_SIZE ); set_zero( dequant_ordered, PARAM_MC_MAX_PARAMETER_BANDS * PARAM_MC_MAX_VAL_MAP_SIZE ); @@ -3157,10 +3163,14 @@ static void ivas_param_mc_bs_decode_parameter_values( for ( i = 0; i < num_lfe_bands; i++ ) { +#ifdef FIX_578_PARAMMC_ILD_BS for ( j = 0; j < n_lfe_idx; j++ ) { dequant_ordered[map_size - n_lfe_idx + j + i * map_size] = dequant_seq[k++]; } +#else + dequant_ordered[map_size - 1 + i * map_size] = dequant_seq[k++]; +#endif } if ( !( *BER_detect ) ) diff --git a/lib_dec/ivas_mcmasa_dec.c b/lib_dec/ivas_mcmasa_dec.c index efdb0a8122809153902ba3c5a4acbee1488f9c62..99b3ff68744b0daf4e3460cd3c9ab3b764ad6bc3 100755 --- a/lib_dec/ivas_mcmasa_dec.c +++ b/lib_dec/ivas_mcmasa_dec.c @@ -82,7 +82,7 @@ ivas_error ivas_mcmasa_dec_reconfig( { if ( st_ivas->hDirAC == NULL ) { - if ( ( error = ivas_dirac_dec_config( st_ivas, DIRAC_OPEN ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_dirac_dec_open( st_ivas ) ) != IVAS_ERR_OK ) { return error; } @@ -96,5 +96,51 @@ ivas_error ivas_mcmasa_dec_reconfig( } } + /*-------------------------------------------------------------------* + * Close binaural rendering handles and re-allocate proper ones + * in McMASA renderer_type can be only RENDERER_BINAURAL_PARAMETRIC, RENDERER_BINAURAL_PARAMETRIC_ROOM + *--------------------------------------------------------------------*/ + + if ( st_ivas->hBinRenderer != NULL ) + { + ivas_binRenderer_close( &st_ivas->hBinRenderer ); + } + + if ( st_ivas->hDiracDecBin == NULL && ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) + { + /* open parametric binaural renderer */ + if ( st_ivas->renderer_type != RENDERER_STEREO_PARAMETRIC ) + { + if ( ( error = ivas_dirac_dec_binaural_copy_hrtfs( &st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + if ( ( error = ivas_dirac_dec_init_binaural_data( st_ivas, st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else if ( st_ivas->hDiracDecBin != NULL ) + { + if ( st_ivas->renderer_type != RENDERER_BINAURAL_PARAMETRIC && st_ivas->renderer_type != RENDERER_BINAURAL_PARAMETRIC_ROOM ) + { + /* close unneeded renderer */ + ivas_dirac_dec_close_binaural_data( &st_ivas->hDiracDecBin ); + } + else + { + /* if necessary, close/open td-decorrs */ + if ( ( error = ivas_td_decorr_reconfig_dec( st_ivas->ivas_format, st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->nchan_transport, st_ivas->hDecoderConfig->output_Fs, &( st_ivas->hDiracDecBin->hTdDecorr ), &( st_ivas->hDiracDecBin->useTdDecorr ) ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* regularization factor is bitrate-dependent */ + st_ivas->hDiracDecBin->reqularizationFactor = configure_reqularization_factor( st_ivas->ivas_format, st_ivas->hDecoderConfig->ivas_total_brate ); + } + } + return error; } diff --git a/lib_dec/ivas_mct_dec.c b/lib_dec/ivas_mct_dec.c index e99cf63fa64376f9ab08878e7d95380cc2f284d8..1350b9656c354f01ba4eaf22c5705c1f0a945589 100755 --- a/lib_dec/ivas_mct_dec.c +++ b/lib_dec/ivas_mct_dec.c @@ -737,13 +737,13 @@ static ivas_error ivas_mc_dec_reconfig( st_ivas->hTcBuffer->slots_rendered = st_ivas->hParamMC->slots_rendered; mvs2s( st_ivas->hParamMC->subframe_nbslots, st_ivas->hTcBuffer->subframe_nbslots, MAX_JBM_SUBFRAMES_5MS ); } - else if ( last_mc_mode == MC_MODE_MCMASA && st_ivas->hSpatParamRendCom != NULL ) + else if ( last_mc_mode == MC_MODE_MCMASA && st_ivas->hDirAC != NULL ) { - st_ivas->hTcBuffer->nb_subframes = st_ivas->hSpatParamRendCom->nb_subframes; - st_ivas->hTcBuffer->subframes_rendered = st_ivas->hSpatParamRendCom->subframes_rendered; - st_ivas->hTcBuffer->num_slots = st_ivas->hSpatParamRendCom->num_slots; - st_ivas->hTcBuffer->slots_rendered = st_ivas->hSpatParamRendCom->slots_rendered; - mvs2s( st_ivas->hSpatParamRendCom->subframe_nbslots, st_ivas->hTcBuffer->subframe_nbslots, MAX_JBM_SUBFRAMES_5MS ); + st_ivas->hTcBuffer->nb_subframes = st_ivas->hDirAC->nb_subframes; + st_ivas->hTcBuffer->subframes_rendered = st_ivas->hDirAC->subframes_rendered; + st_ivas->hTcBuffer->num_slots = st_ivas->hDirAC->num_slots; + st_ivas->hTcBuffer->slots_rendered = st_ivas->hDirAC->slots_rendered; + mvs2s( st_ivas->hDirAC->subframe_nbslots, st_ivas->hTcBuffer->subframe_nbslots, MAX_JBM_SUBFRAMES_5MS ); } /* JBM: when granularity goes down (e.g. MCT with CREND -> ParamMC with binaural fastconv @@ -800,9 +800,7 @@ static ivas_error ivas_mc_dec_reconfig( if ( st_ivas->hDirAC != NULL ) { - ivas_dirac_rend_close( &( st_ivas->hDirACRend ) ); - ivas_spat_hSpatParamRendCom_close( &( st_ivas->hSpatParamRendCom ) ); - ivas_dirac_dec_close( &( st_ivas->hDirAC ) ); + ivas_dirac_dec_close( &st_ivas->hDirAC ); vbap_free_data( &( st_ivas->hVBAPdata ) ); } @@ -886,9 +884,7 @@ static ivas_error ivas_mc_dec_reconfig( if ( st_ivas->hDirAC != NULL ) { - ivas_dirac_rend_close( &( st_ivas->hDirACRend ) ); - ivas_spat_hSpatParamRendCom_close( &( st_ivas->hSpatParamRendCom ) ); - ivas_dirac_dec_close( &( st_ivas->hDirAC ) ); + ivas_dirac_dec_close( &st_ivas->hDirAC ); vbap_free_data( &( st_ivas->hVBAPdata ) ); } @@ -1119,8 +1115,6 @@ static ivas_error ivas_mc_dec_reconfig( } else if ( st_ivas->renderer_type == RENDERER_DISABLE && st_ivas->hDirAC != NULL ) { - ivas_dirac_rend_close( &( st_ivas->hDirACRend ) ); - ivas_spat_hSpatParamRendCom_close( &( st_ivas->hSpatParamRendCom ) ); ivas_dirac_dec_close( &( st_ivas->hDirAC ) ); vbap_free_data( &( st_ivas->hVBAPdata ) ); @@ -1167,6 +1161,16 @@ static ivas_error ivas_mc_dec_reconfig( { ivas_dirac_dec_close_binaural_data( &st_ivas->hDiracDecBin ); } + else + { + /* useTdDecorr may change => close and re-open */ + ivas_dirac_dec_close_binaural_data( &st_ivas->hDiracDecBin ); + + if ( ( error = ivas_dirac_dec_init_binaural_data( st_ivas, st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) + { + return error; + } + } } /* init necessary new renderers */ @@ -1177,6 +1181,21 @@ static ivas_error ivas_mc_dec_reconfig( return error; } } + else if ( st_ivas->hDiracDecBin == NULL && ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) ) + { + if ( st_ivas->renderer_type != RENDERER_STEREO_PARAMETRIC ) + { + if ( ( error = ivas_dirac_dec_binaural_copy_hrtfs( &st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + if ( ( error = ivas_dirac_dec_init_binaural_data( st_ivas, st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) + { + return error; + } + } else if ( st_ivas->hBinRendererTd == NULL && st_ivas->renderer_type == RENDERER_BINAURAL_OBJECTS_TD ) { if ( ( error = ivas_td_binaural_open( st_ivas ) ) != IVAS_ERR_OK ) @@ -1248,6 +1267,18 @@ static ivas_error ivas_mc_dec_reconfig( #endif } + /*-----------------------------------------------------------------* + * TD Decorrelator + *-----------------------------------------------------------------*/ + + if ( st_ivas->hDiracDecBin != NULL ) + { + if ( ( error = ivas_td_decorr_reconfig_dec( st_ivas->ivas_format, st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->nchan_transport, st_ivas->hDecoderConfig->output_Fs, &( st_ivas->hDiracDecBin->hTdDecorr ), &( st_ivas->hDiracDecBin->useTdDecorr ) ) ) != IVAS_ERR_OK ) + { + return error; + } + } + /*-----------------------------------------------------------------* * CLDFB instances *-----------------------------------------------------------------*/ @@ -1293,13 +1324,13 @@ static ivas_error ivas_mc_dec_reconfig( } /* transfer subframe info from central tc buffer to ParamMC or McMASA (DirAC) */ - if ( st_ivas->hSpatParamRendCom != NULL ) + if ( st_ivas->hDirAC != NULL ) { - st_ivas->hSpatParamRendCom->nb_subframes = st_ivas->hTcBuffer->nb_subframes; - st_ivas->hSpatParamRendCom->subframes_rendered = st_ivas->hTcBuffer->subframes_rendered; - st_ivas->hSpatParamRendCom->num_slots = st_ivas->hTcBuffer->num_slots; - st_ivas->hSpatParamRendCom->slots_rendered = st_ivas->hTcBuffer->slots_rendered; - mvs2s( st_ivas->hTcBuffer->subframe_nbslots, st_ivas->hSpatParamRendCom->subframe_nbslots, MAX_JBM_SUBFRAMES_5MS ); + st_ivas->hDirAC->nb_subframes = st_ivas->hTcBuffer->nb_subframes; + st_ivas->hDirAC->subframes_rendered = st_ivas->hTcBuffer->subframes_rendered; + st_ivas->hDirAC->num_slots = st_ivas->hTcBuffer->num_slots; + st_ivas->hDirAC->slots_rendered = st_ivas->hTcBuffer->slots_rendered; + mvs2s( st_ivas->hTcBuffer->subframe_nbslots, st_ivas->hDirAC->subframe_nbslots, MAX_JBM_SUBFRAMES_5MS ); } else if ( st_ivas->hParamMC != NULL ) { diff --git a/lib_dec/ivas_mono_dmx_renderer.c b/lib_dec/ivas_mono_dmx_renderer.c index d4dcb7ac7339e69e50347c4061c68b9547d8a3b9..61d8c6809492ff8ed5ed8e662a3d7ed86838e46b 100644 --- a/lib_dec/ivas_mono_dmx_renderer.c +++ b/lib_dec/ivas_mono_dmx_renderer.c @@ -94,6 +94,21 @@ void ivas_mono_downmix_render_passive( MONO_DOWNMIX_RENDERER_HANDLE hDownmix; numInputChannels = st_ivas->nSCE; + +#ifdef MASA_AND_OBJECTS + if ( st_ivas->ivas_format == MASA_ISM_FORMAT ) + { + if ( st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) + { + numInputChannels = st_ivas->nchan_transport + 1; + } + else + { + numInputChannels = st_ivas->nchan_transport + st_ivas->nchan_ism; + } + } +#endif + hDownmix = st_ivas->hMonoDmxRenderer; set_zero( proto_signal, output_frame ); diff --git a/lib_dec/ivas_objectRenderer_internal.c b/lib_dec/ivas_objectRenderer_internal.c index 3be8a2c62ebfdf1c46806b276c8a7a0c8a54b23d..95ffee7423f56d6779b785e004edc1fe1a927965 100644 --- a/lib_dec/ivas_objectRenderer_internal.c +++ b/lib_dec/ivas_objectRenderer_internal.c @@ -53,8 +53,22 @@ ivas_error ivas_td_binaural_open( Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ ) { +#ifdef MASA_AND_OBJECTS + int16_t num_src; + + num_src = st_ivas->nchan_transport; + if ( st_ivas->ism_mode == ISM_MASA_MODE_DISC ) + { + num_src = st_ivas->nchan_ism; + } + + return ivas_td_binaural_open_unwrap( &st_ivas->hHrtfTD, st_ivas->hDecoderConfig->output_Fs, num_src, st_ivas->ivas_format, + st_ivas->transport_config, st_ivas->hRenderConfig->directivity, st_ivas->hTransSetup, &st_ivas->hBinRendererTd, &st_ivas->binaural_latency_ns ); +#else + return ivas_td_binaural_open_unwrap( &st_ivas->hHrtfTD, st_ivas->hDecoderConfig->output_Fs, st_ivas->nchan_transport, st_ivas->ivas_format, st_ivas->transport_config, st_ivas->hRenderConfig->directivity, st_ivas->hTransSetup, &st_ivas->hBinRendererTd, &st_ivas->binaural_latency_ns ); +#endif } @@ -72,6 +86,17 @@ ivas_error ivas_td_binaural_renderer( ) { int16_t ism_md_subframe_update; +#ifdef MASA_AND_OBJECTS + int16_t num_src; +#endif + +#ifdef MASA_AND_OBJECTS + num_src = st_ivas->nchan_transport; + if ( st_ivas->ism_mode == ISM_MASA_MODE_DISC ) + { + num_src = st_ivas->nchan_ism; + } +#endif if ( st_ivas->hDecoderConfig->Opt_delay_comp ) { @@ -81,10 +106,24 @@ ivas_error ivas_td_binaural_renderer( { ism_md_subframe_update = 2; } + +#ifdef FIX_356_ISM_METADATA_SYNC_OMASA + if ( st_ivas->ivas_format == MASA_ISM_FORMAT ) + { + ism_md_subframe_update = 0; + } +#endif + return ivas_td_binaural_renderer_unwrap( st_ivas->hReverb, st_ivas->transport_config, - st_ivas->hBinRendererTd, st_ivas->nchan_transport, LFE_CHANNEL, st_ivas->ivas_format, + st_ivas->hBinRendererTd, +#ifdef MASA_AND_OBJECTS + num_src, +#else + st_ivas->nchan_transport, +#endif + LFE_CHANNEL, st_ivas->ivas_format, st_ivas->hIsmMetaData, ( st_ivas->hCombinedOrientationData != NULL ) ? st_ivas->hCombinedOrientationData->enableCombinedOrientation : NULL, ( st_ivas->hCombinedOrientationData != NULL ) ? st_ivas->hCombinedOrientationData->Quaternions : NULL, diff --git a/lib_dec/ivas_omasa_dec.c b/lib_dec/ivas_omasa_dec.c new file mode 100644 index 0000000000000000000000000000000000000000..b419da1b59a2524cb48104235f6138154d0a0f80 --- /dev/null +++ b/lib_dec/ivas_omasa_dec.c @@ -0,0 +1,642 @@ +/****************************************************************************************************** + + (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +#include "options.h" +#include +#include "ivas_cnst.h" +#include "ivas_prot.h" +#include "prot.h" +#include "ivas_prot_rend.h" +#include "ivas_rom_com.h" +#ifdef DEBUGGING +#include "debug.h" +#endif + + +#ifdef MASA_AND_OBJECTS +/*-------------------------------------------------------------------* + * ivas_masa_ism_data_open() + * + * Allocate and initialize MASA_ISM rendering handle + *-------------------------------------------------------------------*/ + +ivas_error ivas_masa_ism_data_open( + Decoder_Struct *st_ivas /* i/o: IVAS decoder handle */ +) +{ + MASA_ISM_DATA_HANDLE hMasaIsmData; + int16_t ch, bin; + int16_t sf, obj_idx; + + if ( ( hMasaIsmData = (MASA_ISM_DATA_HANDLE) malloc( sizeof( MASA_ISM_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA ISM data\n" ) ); + } + + for ( bin = 0; bin < CLDFB_NO_CHANNELS_MAX; bin++ ) + { + for ( ch = 0; ch < 2; ch++ ) + { + hMasaIsmData->ismPreprocMatrix[ch][ch][bin] = 1.0f; + hMasaIsmData->ismPreprocMatrix[1 - ch][ch][bin] = 0.0f; + hMasaIsmData->eneMoveIIR[ch][bin] = 0.0f; + hMasaIsmData->enePreserveIIR[ch][bin] = 0.0f; + } + hMasaIsmData->preprocEneTarget[bin] = 0.0f; + hMasaIsmData->preprocEneRealized[bin] = 0.0f; + } + + hMasaIsmData->objectsMoved = 0; + hMasaIsmData->delayBuffer = NULL; + + for ( ch = 0; ch < st_ivas->nchan_ism; ch++ ) + { + hMasaIsmData->q_elevation_old[ch] = 0.0f; + hMasaIsmData->q_azimuth_old[ch] = 0.0f; + } + + for ( obj_idx = 0; obj_idx < MAX_NUM_OBJECTS; obj_idx++ ) + { + set_s( hMasaIsmData->azimuth_ism[obj_idx], 0, MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR ); + set_s( hMasaIsmData->elevation_ism[obj_idx], 0, MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR ); + for ( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR; sf++ ) + { + set_zero( hMasaIsmData->energy_ratio_ism[obj_idx][sf], CLDFB_NO_CHANNELS_MAX ); + } + } + set_s( hMasaIsmData->azimuth_separated_ism, 0, MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR ); + set_s( hMasaIsmData->elevation_separated_ism, 0, MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR ); + + st_ivas->hMasaIsmData = hMasaIsmData; + + return IVAS_ERR_OK; +} + + +/*-------------------------------------------------------------------* + * ivas_masa_ism_data_close() + * + * Deallocate MASA_ISM rendering handle + *-------------------------------------------------------------------*/ + +void ivas_masa_ism_data_close( + MASA_ISM_DATA_HANDLE *hMasaIsmData /* i/o: MASA_ISM rendering handle */ +) +{ + int16_t i; + + if ( hMasaIsmData == NULL || *hMasaIsmData == NULL ) + { + return; + } + + if ( ( *hMasaIsmData )->delayBuffer != NULL ) + { + for ( i = 0; i < ( *hMasaIsmData )->delayBuffer_nchan; i++ ) + { + free( ( *hMasaIsmData )->delayBuffer[i] ); + } + free( ( *hMasaIsmData )->delayBuffer ); + ( *hMasaIsmData )->delayBuffer = NULL; + } + + free( *hMasaIsmData ); + *hMasaIsmData = NULL; + + return; +} + + +/*--------------------------------------------------------------------------* + * ivas_omasa_dec_config() + * + * oMASA decoder configuration + *--------------------------------------------------------------------------*/ + +ivas_error ivas_omasa_dec_config( + Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ +) +{ + int16_t k, sce_id, nSCE_old, nchan_hp20_old, numCldfbAnalyses_old, numCldfbSyntheses_old, n_MD; + int32_t ivas_total_brate, ism_total_brate, cpe_brate; + ISM_MODE ism_mode_old; + IVAS_FORMAT ivas_format_orig; + ivas_error error; + RENDERER_TYPE old_renderer_type; + + /* initializations */ + ism_total_brate = 0; + ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; + + /* save previous frame parameters */ + ism_mode_old = ivas_omasa_ism_mode_select( st_ivas->hDecoderConfig->last_ivas_total_brate, st_ivas->nchan_ism ); + st_ivas->ism_mode = ism_mode_old; + + ivas_format_orig = st_ivas->ivas_format; + st_ivas->ivas_format = st_ivas->last_ivas_format; + ivas_init_dec_get_num_cldfb_instances( st_ivas, &numCldfbAnalyses_old, &numCldfbSyntheses_old ); + st_ivas->ivas_format = ivas_format_orig; + + nSCE_old = st_ivas->nSCE; + nchan_hp20_old = getNumChanSynthesis( st_ivas ); + + /* set ism_mode of current frame */ + st_ivas->ism_mode = ivas_omasa_ism_mode_select( ivas_total_brate, st_ivas->nchan_ism ); + + /*-----------------------------------------------------------------* + * Renderer selection + *-----------------------------------------------------------------*/ + + old_renderer_type = st_ivas->renderer_type; + + /* MASA reconfig. */ + cpe_brate = calculate_cpe_brate_MASA_ISM( st_ivas->ism_mode, ivas_total_brate, st_ivas->nchan_ism ); + if ( st_ivas->ini_active_frame == 0 && ivas_total_brate != FRAME_NO_DATA && ( cpe_brate < MASA_STEREO_MIN_BITRATE ) && st_ivas->nCPE == 1 ) + { + st_ivas->hCPE[0]->nchan_out = 1; + } + else if ( ( error = ivas_masa_dec_reconfigure( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( cpe_brate < MASA_STEREO_MIN_BITRATE ) + { + st_ivas->hCPE[0]->nchan_out = 1; + } + else + { + st_ivas->hCPE[0]->nchan_out = 2; + } + + /* OMASA reconfig. */ + if ( st_ivas->hMasaIsmData == NULL && st_ivas->ivas_format == MASA_ISM_FORMAT ) + { + if ( ( error = ivas_masa_ism_data_open( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + ivas_set_omasa_TC( st_ivas->ism_mode, st_ivas->nchan_ism, &st_ivas->nSCE, &st_ivas->nCPE ); + + /* re-configure hp20 memories */ + if ( ( error = ivas_hp20_dec_reconfig( st_ivas, nchan_hp20_old ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* reconfigure core-coders for ISMs */ + k = 0; + while ( k < SIZE_IVAS_BRATE_TBL && ivas_total_brate != ivas_brate_tbl[k] ) + { + k++; + } + + for ( sce_id = 0; sce_id < st_ivas->nSCE; sce_id++ ) + { + ism_total_brate += sep_object_brate[k - 2][st_ivas->nSCE - 1]; + } + + if ( ( error = ivas_corecoder_dec_reconfig( st_ivas, nSCE_old, 1, 2, 0, st_ivas->nSCE > 0 ? sep_object_brate[k - 2][st_ivas->nSCE - 1] : 0, ivas_total_brate - ism_total_brate ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( ism_mode_old != st_ivas->ism_mode ) + { + /* ISM MD reconfig. */ + n_MD = 0; + + if ( st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) + { + n_MD = 1; + + if ( st_ivas->hIsmMetaData[0] == NULL ) + { + if ( ( error = ivas_ism_metadata_dec_create( st_ivas, 1, NULL ) ) != IVAS_ERR_OK ) + { + return error; + } + } + } + else if ( st_ivas->ism_mode == ISM_MASA_MODE_DISC ) + { + n_MD = st_ivas->nchan_ism; + + ivas_ism_metadata_close( st_ivas->hIsmMetaData, 0 ); + + if ( ( error = ivas_ism_metadata_dec_create( st_ivas, st_ivas->nchan_ism, NULL ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + ivas_ism_metadata_close( st_ivas->hIsmMetaData, n_MD ); + + st_ivas->hCPE[0]->element_brate = ivas_total_brate - ism_total_brate; + + /*-----------------------------------------------------------------* + * Renderer selection + *-----------------------------------------------------------------*/ + + ivas_renderer_select( st_ivas ); + + /*-------------------------------------------------------------------* + * Reallocate rendering handles + *--------------------------------------------------------------------*/ + + if ( old_renderer_type != st_ivas->renderer_type ) + { + if ( st_ivas->renderer_type == RENDERER_MONO_DOWNMIX ) + { + if ( ( error = ivas_mono_dmx_renderer_open( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else + { + if ( st_ivas->hMonoDmxRenderer != NULL ) + { + free( st_ivas->hMonoDmxRenderer ); + st_ivas->hMonoDmxRenderer = NULL; + } + } + } + + /* objects renderer reconfig. */ + if ( st_ivas->ism_mode != ISM_MASA_MODE_MASA_ONE_OBJ && st_ivas->ism_mode != ISM_MASA_MODE_PARAM_ONE_OBJ && st_ivas->ism_mode != ISM_MASA_MODE_DISC && st_ivas->hIsmRendererData != NULL ) + { + ivas_masa_ism_data_close( &( st_ivas->hMasaIsmData ) ); + } + + if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC ) + { + if ( st_ivas->ism_mode == ISM_MASA_MODE_DISC ) + { + /* Allocate TD renderer for the objects in DISC mode */ + if ( ( error = ivas_td_binaural_open( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* Allocate 'hIsmRendererData' handle and memory for delay buffer within 'hMasaIsmData' */ + if ( ( error = ivas_masa_ism_separate_object_renderer_open( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else + { + /* TD renderer handle */ + if ( st_ivas->hBinRendererTd != NULL ) + { + ivas_td_binaural_close( &st_ivas->hBinRendererTd ); + } + + if ( st_ivas->hHrtfTD != NULL ) // VE: this is copied from ivas_ism_bitrate_switching() but a review is needed + { + st_ivas->hHrtfTD = NULL; + } + + /* ISM renderer handle */ + if ( st_ivas->hIsmRendererData != NULL ) + { + free( st_ivas->hIsmRendererData ); + st_ivas->hIsmRendererData = NULL; + } + } + } + + if ( st_ivas->renderer_type == RENDERER_DIRAC ) + { + if ( ( error = ivas_dirac_dec_config( st_ivas, DIRAC_RECONFIGURE ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_DISC ) + { + /* Allocate 'hIsmRendererData' handle and memory for delay buffer within 'hMasaIsmData' */ + if ( ( error = ivas_masa_ism_separate_object_renderer_open( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else + { + /* ISM renderer handle */ + if ( st_ivas->hIsmRendererData != NULL ) + { + free( st_ivas->hIsmRendererData ); + st_ivas->hIsmRendererData = NULL; + } + } + } + + /*-----------------------------------------------------------------* + * TD Decorrelator + *-----------------------------------------------------------------*/ + + if ( st_ivas->hDiracDecBin != NULL ) + { + if ( ( error = ivas_td_decorr_reconfig_dec( st_ivas->ivas_format, st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->nchan_transport, st_ivas->hDecoderConfig->output_Fs, &( st_ivas->hDiracDecBin->hTdDecorr ), &( st_ivas->hDiracDecBin->useTdDecorr ) ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + /*-----------------------------------------------------------------* + * CLDFB instances + *-----------------------------------------------------------------*/ + + if ( ( error = ivas_cldfb_dec_reconfig( st_ivas, 2, numCldfbAnalyses_old, numCldfbSyntheses_old ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + return IVAS_ERR_OK; +} + + +/*--------------------------------------------------------------------------* + * ivas_set_surplus_brate_dec() + * + * set bit-rate surplus in combined format coding + *--------------------------------------------------------------------------*/ + +void ivas_set_surplus_brate_dec( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + int32_t *ism_total_brate /* i/o: ISM total bitrate */ +) +{ + int16_t n, bits_ism, bits_element[MAX_NUM_OBJECTS]; + int32_t ism_total_brate_ref, element_brate[MAX_NUM_OBJECTS]; + + *ism_total_brate = 0; + + if ( st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) + { + *ism_total_brate = ivas_interformat_brate( st_ivas->ism_mode, 1, st_ivas->hSCE[0]->element_brate, st_ivas->hIsmMetaData[0]->ism_imp, 0 ); + + st_ivas->hCPE[0]->brate_surplus = st_ivas->hSCE[0]->element_brate - *ism_total_brate; + + /* set 'st->total_brate'; there are no meta-data in ISM_MASA_MODE_PARAM_ONE_OBJ mode */ + st_ivas->hSCE[0]->hCoreCoder[0]->total_brate = *ism_total_brate; + + st_ivas->hSCE[0]->hCoreCoder[0]->low_rate_mode = 0; + if ( st_ivas->hIsmMetaData[0]->ism_imp == ISM_NO_META ) + { + st_ivas->hSCE[0]->hCoreCoder[0]->low_rate_mode = 1; + } + } + else if ( st_ivas->ism_mode == ISM_MASA_MODE_DISC ) + { + int16_t brate_limit_flag, ism_imp[MAX_NUM_OBJECTS]; + + for ( n = 0; n < st_ivas->nchan_ism; n++ ) + { + ism_imp[n] = st_ivas->hIsmMetaData[n]->ism_imp; + } + + brate_limit_flag = calculate_brate_limit_flag( ism_imp, st_ivas->nchan_ism ); + + ism_total_brate_ref = 0; + for ( n = 0; n < st_ivas->nchan_ism; n++ ) + { + ism_total_brate_ref += st_ivas->hSCE[n]->element_brate; + } + + bits_ism = (int16_t) ( ism_total_brate_ref / FRAMES_PER_SEC ); + set_s( bits_element, bits_ism / st_ivas->nchan_ism, st_ivas->nchan_ism ); + bits_element[st_ivas->nchan_ism - 1] += bits_ism % st_ivas->nchan_ism; + bitbudget_to_brate( bits_element, element_brate, st_ivas->nchan_ism ); + + *ism_total_brate = 0; + for ( n = 0; n < st_ivas->nchan_ism; n++ ) + { + st_ivas->hSCE[n]->element_brate = element_brate[n]; + + *ism_total_brate += ivas_interformat_brate( ISM_MASA_MODE_DISC, st_ivas->nchan_ism, st_ivas->hSCE[n]->element_brate, st_ivas->hIsmMetaData[n]->ism_imp, brate_limit_flag ); + + if ( ism_imp[n] > 1 && st_ivas->flag_omasa_brate == 1 && brate_limit_flag >= 0 ) + { + *ism_total_brate -= ADJUST_ISM_BRATE_NEG; + } + + if ( brate_limit_flag == -1 && ism_imp[n] >= 1 && st_ivas->nchan_ism >= 3 && ( ism_total_brate_ref - *ism_total_brate > IVAS_48k ) ) + { + *ism_total_brate += ADJUST_ISM_BRATE_POS; + } + } + st_ivas->hCPE[0]->brate_surplus = ism_total_brate_ref - *ism_total_brate; + + /* 'st->total_brate' is set in ivas_ism_config */ + } + else + { + st_ivas->hCPE[0]->brate_surplus = 0; + } + + return; +} + + +/*--------------------------------------------------------------------------* + * ivas_omasa_ism_metadata_dec() + * + * decode ISM metadata in OMASA format + *--------------------------------------------------------------------------*/ + +ivas_error ivas_omasa_ism_metadata_dec( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const int32_t ism_total_brate, /* i : ISM total bitrate */ + int16_t *nchan_ism, /* o : number of ISM separated channels */ + int16_t *nchan_transport_ism, /* o : number of ISM TCs */ + const int16_t dirac_bs_md_write_idx, /* i : DirAC bitstream write index */ + int16_t nb_bits_metadata[] /* o : number of ISM metadata bits */ +) +{ + int16_t n, block; + int16_t azimuth_ism, elevation_ism, meta_write_index; + ivas_error error; + + /* set ISM parameters */ + *nchan_ism = st_ivas->nchan_ism; + *nchan_transport_ism = st_ivas->nchan_ism; + if ( st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) + { + *nchan_ism = 1; + *nchan_transport_ism = 1; + } + else if ( st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) + { + *nchan_ism = 0; + *nchan_transport_ism = 1; + } + + if ( st_ivas->ism_mode == ISM_MASA_MODE_DISC || st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) + { + /* decode ISM metadata */ + if ( ( error = ivas_ism_metadata_dec( ism_total_brate, *nchan_ism, nchan_transport_ism, st_ivas->hIsmMetaData, st_ivas->hSCE, st_ivas->bfi, + nb_bits_metadata, st_ivas->ism_mode, st_ivas->hISMDTX, NULL, &st_ivas->ism_extmeta_active, &st_ivas->ism_extmeta_cnt ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( st_ivas->hDirAC != NULL ) + { + if ( st_ivas->ism_mode == ISM_MASA_MODE_DISC ) + { + for ( n = 0; n < st_ivas->nchan_ism; n++ ) + { + azimuth_ism = (int16_t) ( st_ivas->hIsmMetaData[n]->azimuth + 0.5f ); + elevation_ism = (int16_t) ( st_ivas->hIsmMetaData[n]->elevation + 0.5f ); + + for ( block = 0; block < MAX_PARAM_SPATIAL_SUBFRAMES; block++ ) + { + meta_write_index = ( dirac_bs_md_write_idx + block ) % st_ivas->hDirAC->dirac_md_buffer_length; + st_ivas->hMasaIsmData->azimuth_ism[n][meta_write_index] = azimuth_ism; + st_ivas->hMasaIsmData->elevation_ism[n][meta_write_index] = elevation_ism; + } + } + } + else /* ISM_MASA_MODE_MASA_ONE_OBJ */ + { + azimuth_ism = (int16_t) ( st_ivas->hIsmMetaData[0]->azimuth + 0.5f ); + elevation_ism = (int16_t) ( st_ivas->hIsmMetaData[0]->elevation + 0.5f ); + + for ( block = 0; block < MAX_PARAM_SPATIAL_SUBFRAMES; block++ ) + { + meta_write_index = ( dirac_bs_md_write_idx + block ) % st_ivas->hDirAC->dirac_md_buffer_length; + st_ivas->hMasaIsmData->azimuth_separated_ism[meta_write_index] = azimuth_ism; + st_ivas->hMasaIsmData->elevation_separated_ism[meta_write_index] = elevation_ism; + } + } + } + } + + return IVAS_ERR_OK; +} + + +/*--------------------------------------------------------------------------* + * ivas_omasa_dirac_rend() + * + * Rendering in OMASA format + *--------------------------------------------------------------------------*/ + +// Todo OMASA JBM: This might need adjustments +void ivas_omasa_dirac_rend( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + float output[][L_FRAME48k], /* o : output synthesis signal */ + const int16_t output_frame /* i : output frame length per channel */ +) +{ + int16_t n, dirac_read_idx; + float data_separated_objects[MAX_NUM_OBJECTS][L_FRAME48k]; + + if ( st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) + { + mvr2r( output[2], data_separated_objects[0], output_frame ); + } + else + { + for ( n = 0; n < st_ivas->nchan_ism; n++ ) + { + mvr2r( output[n + 2], data_separated_objects[n], output_frame ); + } + } + + dirac_read_idx = st_ivas->hDirAC->dirac_read_idx; + + ivas_dirac_dec( st_ivas, output, st_ivas->nchan_transport ); + + st_ivas->hDirAC->dirac_read_idx = dirac_read_idx; /* Original read index is needed for the next function which will update it again */ + + ivas_masa_ism_separate_object_render( st_ivas, data_separated_objects, output, output_frame ); + + return; +} + + +/*--------------------------------------------------------------------------* + * ivas_omasa_dirac_td_binaural() + * + * Binaural rendering in OMASA format + *--------------------------------------------------------------------------*/ + +ivas_error ivas_omasa_dirac_td_binaural( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + float output[][L_FRAME48k], /* o : output synthesis signal */ + const int16_t output_frame /* i : output frame length per channel */ +) +{ + int16_t n; + float data_separated_objects[MAX_NUM_OBJECTS][L_FRAME48k]; + float gain = 0.7943f; /* Todo Nokia: Temporary gain for roughly matching the loudness of other processing paths. */ + ivas_error error; + float *p_sepobj[MAX_NUM_OBJECTS]; + + for ( n = 0; n < MAX_NUM_OBJECTS; n++ ) + { + p_sepobj[n] = &data_separated_objects[n][0]; + } + + for ( n = 0; n < st_ivas->nchan_ism; n++ ) + { + mvr2r( output[2 + n], data_separated_objects[n], output_frame ); + v_multc( data_separated_objects[n], gain, data_separated_objects[n], output_frame ); + } + + for ( n = 0; n < st_ivas->nchan_ism; n++ ) + { + delay_signal( data_separated_objects[n], output_frame, st_ivas->hMasaIsmData->delayBuffer[n], st_ivas->hMasaIsmData->delayBuffer_size ); + } + + ivas_dirac_dec_binaural( st_ivas, st_ivas->hCombinedOrientationData, output, st_ivas->nchan_transport ); + + if ( ( error = ivas_td_binaural_renderer( st_ivas, p_sepobj, output_frame ) ) != IVAS_ERR_OK ) + { + return error; + } + + for ( n = 0; n < BINAURAL_CHANNELS; n++ ) + { + v_add( output[n], p_sepobj[n], output[n], output_frame ); + } + + return IVAS_ERR_OK; +} +#endif diff --git a/lib_dec/ivas_output_config.c b/lib_dec/ivas_output_config.c index abc9a9012dfe0b90e81193ce49f12716626a2834..fb5469fe43adbd5dcf361c4432f05af9e2b44f22 100644 --- a/lib_dec/ivas_output_config.c +++ b/lib_dec/ivas_output_config.c @@ -147,7 +147,11 @@ void ivas_renderer_select( } } } +#ifdef MASA_AND_OBJECTS + else if ( st_ivas->ivas_format == MASA_FORMAT || st_ivas->ivas_format == MASA_ISM_FORMAT || ( st_ivas->ivas_format == SBA_FORMAT && st_ivas->nchan_transport <= 2 ) ) +#else else if ( st_ivas->ivas_format == MASA_FORMAT || ( st_ivas->ivas_format == SBA_FORMAT && st_ivas->nchan_transport <= 2 ) ) +#endif { *internal_config = output_config; if ( output_config == AUDIO_CONFIG_BINAURAL @@ -424,6 +428,27 @@ void ivas_renderer_select( *renderer_type = RENDERER_SBA_LINEAR_DEC; } } +#ifdef MASA_AND_OBJECTS + else if ( st_ivas->ivas_format == MASA_ISM_FORMAT ) + { + *renderer_type = RENDERER_DIRAC; + + if ( output_config == AUDIO_CONFIG_MONO ) + { + *renderer_type = RENDERER_MONO_DOWNMIX; + } + else if ( output_config == AUDIO_CONFIG_STEREO ) + { + *renderer_type = RENDERER_STEREO_PARAMETRIC; + } +#ifdef OMASA_EXT_OUTPUT + else if ( output_config == AUDIO_CONFIG_EXTERNAL ) + { + *renderer_type = RENDERER_DISABLE; + } +#endif + } +#endif else if ( st_ivas->ivas_format == MC_FORMAT ) { *internal_config = transport_config; diff --git a/lib_dec/ivas_post_proc.c b/lib_dec/ivas_post_proc.c index 417cd7c5b4982e0b28dee6f3f04c60c7b4b70e66..7f1c84983b3834b6948e06c0af71cd88341cc0d0 100755 --- a/lib_dec/ivas_post_proc.c +++ b/lib_dec/ivas_post_proc.c @@ -208,7 +208,11 @@ void stereo_dft_dec_core_switching( lerp( hCPE->input_mem_BPF[0], hCPE->input_mem_BPF[0], NS2SA( st->L_frame * FRAMES_PER_SEC, STEREO_DFT32MS_OVL_NS ), NS2SA( st->last_L_frame * FRAMES_PER_SEC, STEREO_DFT32MS_OVL_NS ) ); } +#ifdef FIX_558_PLC_DISCONT if ( st->prev_bfi && !( st->last_core_bfi == ACELP_CORE && st->last_con_tcx == 1 ) ) +#else + if ( st->prev_bfi ) +#endif { /* last_core needed for correctly decoding ACELP->TCX/HQ switching frames in ivas_core_dec(). In the following steps the decoder needs to consider if the core was changed due to a lost frame to apply the correct transition */ diff --git a/lib_dec/ivas_qmetadata_dec.c b/lib_dec/ivas_qmetadata_dec.c index e4c69cd288a01bdc124ae7e289fe2befc6eb75b0..97209faf7ca760d0ecbedaf5678f0660ada2557a 100644 --- a/lib_dec/ivas_qmetadata_dec.c +++ b/lib_dec/ivas_qmetadata_dec.c @@ -55,7 +55,9 @@ static int16_t ivas_qmetadata_raw_decode_dir( IVAS_QDIRECTION *q_direction, uint static uint16_t ivas_qmetadata_DecodeQuasiUniform( const uint16_t *bitstream, int16_t *index, const uint16_t alphabet_size ); +#ifndef MASA_AND_OBJECTS static int16_t ivas_qmetadata_DecodeExtendedGR( uint16_t *bitstream, int16_t *index, const int16_t alph_size, const int16_t gr_param ); +#endif static int16_t ivas_qmetadata_ReorderElevationDecoded( const int16_t elev_dist, const int16_t elev_avg, const int16_t elev_alph ); @@ -101,6 +103,10 @@ 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 ); +#ifdef MASA_AND_OBJECTS +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 ); +#endif + /*-----------------------------------------------------------------------* * Global function definitions @@ -607,6 +613,7 @@ int16_t ivas_qmetadata_dec_decode( bits_dir_target += bits_dir_raw; bits_dir_used += bits_dir; + #ifdef DEBUG_MODE_QMETADATA fprintf( pF, "frame %d: diff %d coh %d surcoh %d ", frame, bits_diff, bits_coherence, bits_sur_coherence ); fprintf( pF, "dir %d %d,%d,%d\n", ec_flag, start_index_0 - *index, total_bits_1dir, bits_dir_raw ); @@ -962,6 +969,7 @@ int16_t ivas_qmetadata_dec_decode_hr_384_512( } } #else +#ifdef FIX_566_2DIR_MASA_384K float ratioSum; for ( b = hQMetaData->q_direction[1].cfg.start_band; b < hQMetaData->q_direction[1].cfg.nbands; b++ ) { @@ -979,6 +987,19 @@ int16_t ivas_qmetadata_dec_decode_hr_384_512( } } } +#else + for ( b = hQMetaData->q_direction[1].cfg.start_band; b < hQMetaData->q_direction[1].cfg.nbands; b++ ) + { + for ( m = 0; m < hQMetaData->q_direction[1].cfg.nblocks; m++ ) + { + hQMetaData->q_direction[1].band_data[b].energy_ratio[m] = 1.0f - diffuseness_reconstructions_hr[hQMetaData->q_direction[1].band_data[b].energy_ratio_index[m]]; + if ( hQMetaData->q_direction[1].band_data[b].energy_ratio[m] > 1.0f - hQMetaData->q_direction[0].band_data[b].energy_ratio[m] ) + { + hQMetaData->q_direction[1].band_data[b].energy_ratio[m] = 1.0f - hQMetaData->q_direction[0].band_data[b].energy_ratio[m]; + } + } + } +#endif #endif } @@ -2403,12 +2424,16 @@ static uint16_t ivas_qmetadata_DecodeQuasiUniform( *------------------------------------------------------------------------*/ /*! r: Value decoded from the bitstream */ -static int16_t ivas_qmetadata_DecodeExtendedGR( - uint16_t *bitstream, /* i : pointer to the bitstream to read */ - int16_t *index, /* i/o: position in the bitstream to start reading (gets updated with reading) */ - const int16_t alph_size, /* i : size of the alphabet, used to calculate the number of bits needed */ - const int16_t gr_param /* i : GR parameter that indicates the limit for the most significant bits (msb) */ -) +#ifndef MASA_AND_OBJECTS +static +#endif + int16_t + ivas_qmetadata_DecodeExtendedGR( + uint16_t *bitstream, /* i : pointer to the bitstream to read */ + int16_t *index, /* i/o: position in the bitstream to start reading (gets updated with reading) */ + const int16_t alph_size, /* i : size of the alphabet, used to calculate the number of bits needed */ + const int16_t gr_param /* i : GR parameter that indicates the limit for the most significant bits (msb) */ + ) { int16_t i, msb_size; uint16_t value; @@ -4394,3 +4419,205 @@ static void decode_combined_index( return; } + + +#ifdef MASA_AND_OBJECTS +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 ) +{ + int16_t sign, nbits; + int16_t i, j, i_min; + + float step; + int16_t GR1, GR2; + + step = STEP_M2T; + nbits = 0; + sign = 1; + if ( first_line == 0 ) + { + /* read sign */ + sign = bit_stream[( *index )--]; + if ( sign == 0 ) + { + sign = -1; + } + nbits++; + } + + set_s( q_idx, 0, len_stream ); + /* read DCT 0 component */ + for ( i = 0; i < BITS_MASA2TOTTAL_DCT0; i++ ) + { + q_idx[0] = ( q_idx[0] << 1 ) + bit_stream[( *index )--]; + } + q_idx[0] *= sign; + + if ( q_idx[0] != 0 ) + { + if ( len_stream >= 8 ) + { + /* read index of last index encoded with GR2 */ + i_min = 0; + j = 4; + for ( i = 0; i < j; i++ ) + { + i_min = ( i_min << 1 ) + bit_stream[( *index )--]; + } + nbits += j; + /* read GR orders */ + GR1 = bit_stream[( *index )--] + 1; + if ( GR1 == 2 ) + { + GR2 = bit_stream[( *index )--]; + } + else + { + GR2 = 0; + } + + /* read GR data */ + for ( i = 1; i <= i_min; i++ ) + { + q_idx[i] = ivas_qmetadata_DecodeExtendedGR( bit_stream, index, 100, GR1 ); + } + for ( i = i_min + 1; i < len_stream; i++ ) + { + q_idx[i] = ivas_qmetadata_DecodeExtendedGR( bit_stream, index, 100, GR2 ); + } + } + else + { + /* read GR order (only one) */ + GR1 = bit_stream[( *index )--]; + for ( i = 1; i < len_stream; i++ ) + { + q_idx[i] = ivas_qmetadata_DecodeExtendedGR( bit_stream, index, 100, GR1 ); + } + } + } + + /* deindex */ + q_dct_data[0] = q_idx[0] * step; + for ( i = 1; i < len_stream; i++ ) + { + if ( ( q_idx[i] % 2 ) == 0 ) + { + q_dct_data[i] = -( q_idx[i] >> 1 ) * step; + } + else + { + q_dct_data[i] = ( ( q_idx[i] + 1 ) >> 1 ) * step; + } + } + + return; +} + + +/*------------------------------------------------------------------------- + * decode_masa_to_total() + * + *------------------------------------------------------------------------*/ + +void decode_masa_to_total( + uint16_t *bit_stream, + int16_t *index, + float masa_to_total_energy_ratio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], + const int16_t nbands, + const int16_t nblocks ) +{ + int16_t i, j, k; + int16_t q_idx[MAX_PARAM_SPATIAL_SUBFRAMES * MASA_FREQUENCY_BANDS]; + float q_dct_data[MAX_PARAM_SPATIAL_SUBFRAMES * MASA_FREQUENCY_BANDS], + dct_data_tmp[MAX_PARAM_SPATIAL_SUBFRAMES * MASA_FREQUENCY_BANDS]; + int16_t n_streams, len_stream; + + /* Setup coding parameters */ + n_streams = 1; + len_stream = nbands * nblocks; + if ( len_stream == 32 ) + { + n_streams = 4; + len_stream = 8; + } + + 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 ); + } + + /* inverse DCT2 transform */ + switch ( len_stream ) + { + case 4: + matrix_product( dct4, nblocks, nblocks, 1, q_dct_data, nblocks, 1, 0, dct_data_tmp ); + mvr2r( dct_data_tmp, q_dct_data, nblocks ); + break; + case 5: + matrix_product( dct5, nbands, nbands, 1, q_dct_data, nbands, 1, 0, dct_data_tmp ); + mvr2r( dct_data_tmp, q_dct_data, nbands ); + break; + case 8: + matrix_product( dct8, nbands, nbands, 1, q_dct_data, nbands, 1, 0, dct_data_tmp ); + mvr2r( dct_data_tmp, q_dct_data, nbands ); + break; + case 12: + matrix_product( dct12, nbands, nbands, 1, q_dct_data, nbands, 1, 0, dct_data_tmp ); + mvr2r( dct_data_tmp, q_dct_data, nbands ); + break; + case 20: + matrix_product( dct5, nbands, nbands, 1, q_dct_data, nbands, nblocks, 0, dct_data_tmp ); + matrix_product( dct_data_tmp, nbands, nblocks, 0, dct4, nblocks, nblocks, 0, q_dct_data ); /* reuse of variable*/ + break; + case 32: + matrix_product( dct8, nbands, nbands, 1, q_dct_data, nbands, nblocks, 0, dct_data_tmp ); + matrix_product( dct_data_tmp, nbands, nblocks, 0, dct4, nblocks, nblocks, 0, q_dct_data ); + break; + default: + printf( "Incorrect number of coefficients for OMASA.\n" ); + break; + } + + k = 0; + for ( i = 0; i < nblocks; i++ ) + { + for ( j = 0; j < nbands; j++ ) + { + 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] ); + 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]; + } + } + } + + return; +} +#endif diff --git a/lib_dec/ivas_sba_dec.c b/lib_dec/ivas_sba_dec.c index 763a1b222fde2f2c596e3f0239a9ea812788475c..fb97faf0de1c23cd02e987813e119e1f4868534b 100755 --- a/lib_dec/ivas_sba_dec.c +++ b/lib_dec/ivas_sba_dec.c @@ -65,7 +65,7 @@ void ivas_sba_set_cna_cng_flag( /* st_ivas->hSCE[0]->hCoreCoder[0]->cna_dirac_flag = 0; */ /* st_ivas->hSCE[0]->hCoreCoder[0]->cng_sba_flag = 0; */ } - else if ( st_ivas->nchan_transport == 1 && ( ( st_ivas->renderer_type == RENDERER_DIRAC && st_ivas->hDirACRend->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) || ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) ) ) + else if ( st_ivas->nchan_transport == 1 && ( ( st_ivas->renderer_type == RENDERER_DIRAC && st_ivas->hDirAC->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) || ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) ) ) { st_ivas->hSCE[0]->hCoreCoder[0]->cna_dirac_flag = 1; st_ivas->hSCE[0]->hCoreCoder[0]->cng_sba_flag = 1; @@ -114,6 +114,8 @@ ivas_error ivas_sba_dec_reconfigure( int16_t num_channels, num_md_sub_frames; #endif + RENDERER_TYPE old_renderer_type; + DECODER_CONFIG_HANDLE hDecoderConfig; ivas_error error; error = IVAS_ERR_OK; @@ -145,13 +147,13 @@ ivas_error ivas_sba_dec_reconfigure( st_ivas->hTcBuffer->subframes_rendered = st_ivas->hSpar->subframes_rendered; mvs2s( st_ivas->hSpar->subframe_nbslots, st_ivas->hTcBuffer->subframe_nbslots, MAX_JBM_SUBFRAMES_5MS ); } - else if ( st_ivas->hSpatParamRendCom != NULL ) + else if ( st_ivas->hDirAC != NULL ) { - st_ivas->hTcBuffer->num_slots = st_ivas->hSpatParamRendCom->num_slots; - st_ivas->hTcBuffer->nb_subframes = st_ivas->hSpatParamRendCom->nb_subframes; - st_ivas->hTcBuffer->slots_rendered = st_ivas->hSpatParamRendCom->slots_rendered; - st_ivas->hTcBuffer->subframes_rendered = st_ivas->hSpatParamRendCom->subframes_rendered; - mvs2s( st_ivas->hSpatParamRendCom->subframe_nbslots, st_ivas->hTcBuffer->subframe_nbslots, MAX_JBM_SUBFRAMES_5MS ); + st_ivas->hTcBuffer->num_slots = st_ivas->hDirAC->num_slots; + st_ivas->hTcBuffer->nb_subframes = st_ivas->hDirAC->nb_subframes; + st_ivas->hTcBuffer->slots_rendered = st_ivas->hDirAC->slots_rendered; + st_ivas->hTcBuffer->subframes_rendered = st_ivas->hDirAC->subframes_rendered; + mvs2s( st_ivas->hDirAC->subframe_nbslots, st_ivas->hTcBuffer->subframe_nbslots, MAX_JBM_SUBFRAMES_5MS ); } /*-----------------------------------------------------------------* @@ -238,6 +240,7 @@ ivas_error ivas_sba_dec_reconfigure( /* renderer might have changed */ intern_config_old = st_ivas->intern_config; + old_renderer_type = st_ivas->renderer_type; ivas_renderer_select( st_ivas ); /* side effect of the renderer selection can be a changed internal config */ @@ -290,6 +293,29 @@ ivas_error ivas_sba_dec_reconfigure( #endif } + if ( st_ivas->renderer_type != old_renderer_type ) + { + if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) + { + if ( st_ivas->renderer_type != RENDERER_STEREO_PARAMETRIC ) + { + if ( ( error = ivas_dirac_dec_binaural_copy_hrtfs( &st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + if ( ( error = ivas_dirac_dec_init_binaural_data( st_ivas, st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) + { + return error; + } + } + } + else if ( st_ivas->hDiracDecBin != NULL && ( st_ivas->renderer_type != RENDERER_BINAURAL_PARAMETRIC && st_ivas->renderer_type != RENDERER_BINAURAL_PARAMETRIC_ROOM && st_ivas->renderer_type != RENDERER_STEREO_PARAMETRIC ) ) + { + ivas_dirac_dec_close_binaural_data( &st_ivas->hDiracDecBin ); + } + if ( ( ( st_ivas->renderer_type != RENDERER_DISABLE ) && ( st_ivas->renderer_type != RENDERER_SBA_LINEAR_DEC ) ) || ( ( hDecoderConfig->output_config != AUDIO_CONFIG_FOA ) && ( st_ivas->hDecoderConfig->output_config != AUDIO_CONFIG_STEREO ) && ( st_ivas->hDecoderConfig->output_config != AUDIO_CONFIG_MONO ) ) || ( last_ivas_total_brate > IVAS_256k && ivas_total_brate <= IVAS_256k ) || ( last_ivas_total_brate <= IVAS_256k && ivas_total_brate > IVAS_256k ) ) { DIRAC_CONFIG_FLAG flag_config; @@ -306,14 +332,11 @@ ivas_error ivas_sba_dec_reconfigure( } /* synchronize subframe info */ - if ( st_ivas->hSpatParamRendCom != NULL ) - { - st_ivas->hSpatParamRendCom->num_slots = st_ivas->hTcBuffer->num_slots; - st_ivas->hSpatParamRendCom->nb_subframes = st_ivas->hTcBuffer->nb_subframes; - st_ivas->hSpatParamRendCom->slots_rendered = st_ivas->hTcBuffer->slots_rendered; - st_ivas->hSpatParamRendCom->subframes_rendered = st_ivas->hTcBuffer->subframes_rendered; - mvs2s( st_ivas->hTcBuffer->subframe_nbslots, st_ivas->hSpatParamRendCom->subframe_nbslots, MAX_JBM_SUBFRAMES_5MS ); - } + st_ivas->hDirAC->num_slots = st_ivas->hTcBuffer->num_slots; + st_ivas->hDirAC->nb_subframes = st_ivas->hTcBuffer->nb_subframes; + st_ivas->hDirAC->slots_rendered = st_ivas->hTcBuffer->slots_rendered; + st_ivas->hDirAC->subframes_rendered = st_ivas->hTcBuffer->subframes_rendered; + mvs2s( st_ivas->hTcBuffer->subframe_nbslots, st_ivas->hDirAC->subframe_nbslots, MAX_JBM_SUBFRAMES_5MS ); } if ( ( error = ivas_dirac_sba_config( st_ivas->hQMetaData, &st_ivas->element_mode_init, ivas_total_brate, st_ivas->sba_analysis_order, ivas_get_hodirac_flag( ivas_total_brate, st_ivas->sba_analysis_order ) ? IVAS_MAX_NUM_BANDS : ( IVAS_MAX_NUM_BANDS - SPAR_DIRAC_SPLIT_START_BAND ) ) ) != IVAS_ERR_OK ) @@ -323,8 +346,6 @@ ivas_error ivas_sba_dec_reconfigure( if ( st_ivas->renderer_type == RENDERER_DISABLE ) { - ivas_dirac_rend_close( &( st_ivas->hDirACRend ) ); - ivas_spat_hSpatParamRendCom_close( &( st_ivas->hSpatParamRendCom ) ); ivas_dirac_dec_close( &( st_ivas->hDirAC ) ); vbap_free_data( &( st_ivas->hVBAPdata ) ); @@ -403,7 +424,7 @@ ivas_error ivas_sba_dec_reconfigure( } else { - if ( st_ivas->nchan_transport == 1 && ( ( st_ivas->renderer_type == RENDERER_DIRAC && st_ivas->hDirACRend->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) || ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) ) + if ( st_ivas->nchan_transport == 1 && ( ( st_ivas->renderer_type == RENDERER_DIRAC && st_ivas->hDirAC->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) || ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) ) { tc_nchan_to_allocate++; /* we need a channel for the CNG in this case*/ } @@ -510,11 +531,9 @@ void ivas_sba_dec_render( uint16_t slot_size, ch; uint16_t nchan_internal, nchan_out; SPAR_DEC_HANDLE hSpar; - SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom; float *output_f_local[MAX_OUTPUT_CHANNELS]; hSpar = st_ivas->hSpar; - hSpatParamRendCom = st_ivas->hSpatParamRendCom; nchan_internal = ivas_sba_get_nchan_metadata( st_ivas->sba_analysis_order, st_ivas->hDecoderConfig->ivas_total_brate ); nchan_out = st_ivas->hIntSetup.nchan_out_woLFE + st_ivas->hIntSetup.num_lfe; @@ -563,11 +582,11 @@ void ivas_sba_dec_render( { if ( st_ivas->hDirAC->hConfig->dec_param_estim == 1 ) { - hSpatParamRendCom->dirac_read_idx = ( hSpatParamRendCom->dirac_read_idx + DEFAULT_JBM_CLDFB_TIMESLOTS ) % hSpatParamRendCom->dirac_md_buffer_length; + st_ivas->hDirAC->dirac_read_idx = ( st_ivas->hDirAC->dirac_read_idx + DEFAULT_JBM_CLDFB_TIMESLOTS ) % st_ivas->hDirAC->dirac_md_buffer_length; } else { - hSpatParamRendCom->dirac_read_idx = ( hSpatParamRendCom->dirac_read_idx + DEFAULT_JBM_SUBFRAMES_5MS ) % hSpatParamRendCom->dirac_md_buffer_length; + st_ivas->hDirAC->dirac_read_idx = ( st_ivas->hDirAC->dirac_read_idx + DEFAULT_JBM_SUBFRAMES_5MS ) % st_ivas->hDirAC->dirac_md_buffer_length; } } diff --git a/lib_dec/ivas_sce_dec.c b/lib_dec/ivas_sce_dec.c index 9bb7fc227d17823c66bd1958479d71b9f8ecd302..cae8f13ef1bdc97c7de4d7c26df56dd814e78ecb 100755 --- a/lib_dec/ivas_sce_dec.c +++ b/lib_dec/ivas_sce_dec.c @@ -123,8 +123,12 @@ ivas_error ivas_sce_dec( /* only WB is supported */ st->bwidth = WB; } +#ifdef ISM_FB else if ( ( hSCE->element_brate < MIN_BRATE_FB_STEREO && !st->is_ism_format ) || ( hSCE->element_brate < MIN_BRATE_FB_ISM && st->is_ism_format ) ) +#else + else if ( hSCE->element_brate < MIN_BRATE_FB_STEREO ) +#endif { /* WB and SWB are supported */ st->bwidth = get_next_indice( st, 1 ) + WB; @@ -153,7 +157,15 @@ ivas_error ivas_sce_dec( if ( ( st_ivas->hQMetaData != NULL ) && ( st_ivas->ivas_format != SBA_FORMAT ) ) { +#ifdef MASA_AND_OBJECTS + if ( st_ivas->ism_mode == ISM_MASA_MODE_DISC || st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) + { + st->bits_frame_nominal = (int16_t) ( ( hSCE->element_brate / FRAMES_PER_SEC ) - ISM_NB_BITS_METADATA_NOMINAL ); + } + else if ( ( st_ivas->mc_mode == MC_MODE_MCMASA && ivas_total_brate >= MCMASA_SEPARATE_BRATE ) || ( st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) ) +#else if ( st_ivas->mc_mode == MC_MODE_MCMASA && ivas_total_brate >= MCMASA_SEPARATE_BRATE ) +#endif { st->bits_frame_nominal = (int16_t) ( hSCE->element_brate / FRAMES_PER_SEC ); } @@ -171,6 +183,7 @@ ivas_error ivas_sce_dec( st->bits_frame_nominal = (int16_t) ( ( hSCE->element_brate / FRAMES_PER_SEC ) - ISM_NB_BITS_METADATA_NOMINAL ); } + /* set "total_brate" */ if ( !st_ivas->bfi && ivas_total_brate == IVAS_SID_5k2 ) { @@ -185,16 +198,36 @@ ivas_error ivas_sce_dec( { st->total_brate = ivas_total_brate; } +#ifndef FIX_565_SBA_BURST_IN_FEC +#ifdef MASA_AND_OBJECTS + else if ( st_ivas->ivas_format != ISM_FORMAT && st_ivas->ivas_format != MASA_ISM_FORMAT ) /* note: total_brate[] is set in ivas_ism_config() or ivas_set_surplus_brate_dec() */ +#else + else if ( st_ivas->ivas_format != ISM_FORMAT ) /* note: in ISMs, total_brate[] is set in ivas_ism_config() */ +#endif + { + st->total_brate = hSCE->element_brate - nb_bits_metadata * FRAMES_PER_SEC; + } +#else +#ifdef MASA_AND_OBJECTS + else if ( !st_ivas->bfi && st_ivas->ivas_format != ISM_FORMAT && st_ivas->ivas_format != MASA_ISM_FORMAT ) /* note: in ISMs, total_brate[] is set in ivas_ism_config() */ +#else else if ( !st_ivas->bfi && st_ivas->ivas_format != ISM_FORMAT ) /* note: in ISMs, total_brate[] is set in ivas_ism_config() */ +#endif { st->total_brate = hSCE->element_brate - nb_bits_metadata * FRAMES_PER_SEC; } +#endif /*----------------------------------------------------------------* * Core codec configuration *----------------------------------------------------------------*/ - /* set ACELP12k8 / ACELP16k flag for flexible ACELP core */ +/* set ACELP12k8 / ACELP16k flag for flexible ACELP core */ +#ifdef MASA_AND_OBJECTS + if ( ( st_ivas->ivas_format == ISM_FORMAT || st_ivas->ism_mode == ISM_MASA_MODE_DISC || st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) && + st->low_rate_mode && !( st->total_brate == SID_2k40 || st->total_brate == FRAME_NO_DATA ) ) +#else if ( st_ivas->ivas_format == ISM_FORMAT && st->low_rate_mode && !( st->total_brate == SID_2k40 || st->total_brate == FRAME_NO_DATA ) ) +#endif { st->flag_ACELP16k = 0; } @@ -290,9 +323,15 @@ ivas_error ivas_sce_dec( dbgwrite( &st->element_mode, sizeof( int16_t ), 1, output_frame, fname( debug_dir, "element_mode", 0, sce_id, DEC ) ); dbgwrite( output, sizeof( float ), output_frame, 1, fname( debug_dir, "output.sce", 0, sce_id, DEC ) ); - tmpF = 0; - dbgwrite( &tmpF, sizeof( float ), 1, output_frame, fname( debug_dir, "output.cpe", 0, sce_id, DEC ) ); - dbgwrite( &tmpF, sizeof( float ), 1, output_frame, fname( debug_dir, "output.mct", 0, sce_id, DEC ) ); + +#ifdef MASA_AND_OBJECTS + if ( st_ivas->ivas_format != MASA_ISM_FORMAT ) + { + tmpF = 0; + dbgwrite( &tmpF, sizeof( float ), 1, output_frame, fname( debug_dir, "output.cpe", 0, sce_id, DEC ) ); + dbgwrite( &tmpF, sizeof( float ), 1, output_frame, fname( debug_dir, "output.mct", 0, sce_id, DEC ) ); + } +#endif } } #endif @@ -355,7 +394,11 @@ ivas_error create_sce_dec( st->total_brate = hSCE->element_brate; /* dummy initialization for getting right pointers initialization of input buffers in init_coder_ace_plus() */ st->mct_chan_mode = MCT_CHAN_MODE_REGULAR; st->is_ism_format = 0; +#ifdef MASA_AND_OBJECTS + if ( st_ivas->ivas_format == ISM_FORMAT || st_ivas->ivas_format == MASA_ISM_FORMAT ) +#else if ( st_ivas->ivas_format == ISM_FORMAT ) +#endif { st->is_ism_format = 1; } diff --git a/lib_dec/ivas_spar_decoder.c b/lib_dec/ivas_spar_decoder.c index 1c839316e52fefb4ad4f4e44bc7d7533cd95efe8..79ed6c7cf3d67400f11897d8c13f8fd491553a0c 100644 --- a/lib_dec/ivas_spar_decoder.c +++ b/lib_dec/ivas_spar_decoder.c @@ -325,7 +325,7 @@ ivas_error ivas_spar_dec( /* read DirAC bitstream */ if ( st_ivas->hQMetaData != NULL ) { - ivas_dirac_dec_read_BS( hDecoderConfig->ivas_total_brate, st0, st_ivas->hDirAC, st_ivas->hSpatParamRendCom, st_ivas->hQMetaData, nb_bits_read, + ivas_dirac_dec_read_BS( hDecoderConfig->ivas_total_brate, st0, st_ivas->hDirAC, st_ivas->hQMetaData, nb_bits_read, ivas_get_hodirac_flag( hDecoderConfig->ivas_total_brate, st_ivas->sba_analysis_order ), st_ivas->hSpar->dirac_to_spar_md_bands ); } @@ -345,7 +345,9 @@ ivas_error ivas_spar_dec( st0->bit_stream = bstr_meta; st0->next_bit_pos = 0; st0->bits_frame = min( MAX_BITS_METADATA, last_bit_pos + 1 ); +#ifdef FIX_565_SBA_BURST_IN_FEC if ( !st0->bfi ) +#endif { st0->total_brate = hDecoderConfig->ivas_total_brate; /* to avoid BER detect */ } @@ -1311,7 +1313,6 @@ void ivas_spar_dec_upmixer( ) { SPAR_DEC_HANDLE hSpar; - SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom; int16_t nchan_transport, nchan_out; int16_t subframe_idx, n, i; int16_t n_samples_sf; @@ -1391,16 +1392,15 @@ void ivas_spar_dec_upmixer( st_ivas->hTcBuffer->tc[n] = NULL; } - if ( st_ivas->hDirAC != NULL && st_ivas->hSpatParamRendCom != NULL ) + if ( st_ivas->hDirAC != 0 ) { - hSpatParamRendCom = st_ivas->hSpatParamRendCom; if ( st_ivas->hDirAC->hConfig->dec_param_estim == 1 ) { - hSpatParamRendCom->dirac_read_idx = ( hSpatParamRendCom->dirac_read_idx + DEFAULT_JBM_CLDFB_TIMESLOTS ) % hSpatParamRendCom->dirac_md_buffer_length; + st_ivas->hDirAC->dirac_read_idx = ( st_ivas->hDirAC->dirac_read_idx + DEFAULT_JBM_CLDFB_TIMESLOTS ) % st_ivas->hDirAC->dirac_md_buffer_length; } else { - hSpatParamRendCom->dirac_read_idx = ( hSpatParamRendCom->dirac_read_idx + DEFAULT_JBM_SUBFRAMES_5MS ) % hSpatParamRendCom->dirac_md_buffer_length; + st_ivas->hDirAC->dirac_read_idx = ( st_ivas->hDirAC->dirac_read_idx + DEFAULT_JBM_SUBFRAMES_5MS ) % st_ivas->hDirAC->dirac_md_buffer_length; } } @@ -1689,7 +1689,7 @@ void ivas_spar_dec_upmixer_sf( if ( ( st_ivas->hOutSetup.num_lfe > 0 ) && ( st_ivas->hOutSetup.index_lfe[idx_lfe] == ch ) ) { set_zero( output[ch], hSpar->subframe_nbslots[hSpar->subframes_rendered] * num_cldfb_bands ); - if ( idx_lfe < ( st_ivas->hDirACRend->hOutSetup.num_lfe - 1 ) ) + if ( idx_lfe < ( st_ivas->hDirAC->hOutSetup.num_lfe - 1 ) ) { idx_lfe++; } diff --git a/lib_dec/ivas_spar_md_dec.c b/lib_dec/ivas_spar_md_dec.c index c61effd67359f2e1873e7230e1ddda0e154b4b38..a1d3e9839276bac93dc0eab7d026314f0697d885 100644 --- a/lib_dec/ivas_spar_md_dec.c +++ b/lib_dec/ivas_spar_md_dec.c @@ -3051,9 +3051,6 @@ void ivas_spar_to_dirac( end_band = min( num_bands_out, SPAR_DIRAC_SPLIT_START_BAND ) / bw; hDirAC = st_ivas->hDirAC; - SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom; - hSpatParamRendCom = st_ivas->hSpatParamRendCom; - dirac_to_spar_md_bands = st_ivas->hSpar->dirac_to_spar_md_bands; enc_param_start_band = st_ivas->hSpar->enc_param_start_band / bw; active_w_vlbr = ( st_ivas->hDecoderConfig->ivas_total_brate < IVAS_24k4 ) ? 1 : 0; @@ -3148,46 +3145,46 @@ void ivas_spar_to_dirac( { int16_t ts_start, ts_end, ts; - ts_start = DirAC_block_grouping[block]; - ts_end = DirAC_block_grouping[block + 1]; + ts_start = hDirAC->block_grouping[block]; + ts_end = hDirAC->block_grouping[block + 1]; for ( b = qmf_band_start; b < qmf_band_end; b++ ) { azi_dith = azi[band]; ele_dith = ele[band]; - hSpatParamRendCom->energy_ratio1[block][b] = en_ratio; + hDirAC->energy_ratio1[block][b] = en_ratio; tmp_write_idx_band = tmp_write_idx_param_band; if ( hDirAC->hConfig->dec_param_estim == FALSE ) { - hSpatParamRendCom->elevation[tmp_write_idx_band][b] = ele_dith; - hSpatParamRendCom->azimuth[tmp_write_idx_band][b] = azi_dith; - hSpatParamRendCom->diffuseness_vector[tmp_write_idx_band][b] = diffuseness[band]; + hDirAC->elevation[tmp_write_idx_band][b] = ele_dith; + hDirAC->azimuth[tmp_write_idx_band][b] = azi_dith; + hDirAC->diffuseness_vector[tmp_write_idx_band][b] = diffuseness[band]; } else { for ( ts = ts_start; ts < ts_end; ts++ ) { - hSpatParamRendCom->elevation[tmp_write_idx_band][b] = ele_dith; - hSpatParamRendCom->azimuth[tmp_write_idx_band][b] = azi_dith; - hSpatParamRendCom->diffuseness_vector[tmp_write_idx_band][b] = diffuseness[band]; - tmp_write_idx_band = ( tmp_write_idx_band + 1 ) % hSpatParamRendCom->dirac_md_buffer_length; + hDirAC->elevation[tmp_write_idx_band][b] = ele_dith; + hDirAC->azimuth[tmp_write_idx_band][b] = azi_dith; + hDirAC->diffuseness_vector[tmp_write_idx_band][b] = diffuseness[band]; + tmp_write_idx_band = ( tmp_write_idx_band + 1 ) % hDirAC->dirac_md_buffer_length; } } } - tmp_write_idx_param_band = ( tmp_write_idx_param_band + num_slots_in_subfr ) % hSpatParamRendCom->dirac_md_buffer_length; + tmp_write_idx_param_band = ( tmp_write_idx_param_band + num_slots_in_subfr ) % hDirAC->dirac_md_buffer_length; } } /* update buffer write index */ if ( hDirAC->hConfig->dec_param_estim == FALSE ) { - hDirAC->spar_to_dirac_write_idx = ( hDirAC->spar_to_dirac_write_idx + MAX_PARAM_SPATIAL_SUBFRAMES ) % hSpatParamRendCom->dirac_md_buffer_length; + hDirAC->spar_to_dirac_write_idx = ( hDirAC->spar_to_dirac_write_idx + MAX_PARAM_SPATIAL_SUBFRAMES ) % hDirAC->dirac_md_buffer_length; } else { - hDirAC->spar_to_dirac_write_idx = ( hDirAC->spar_to_dirac_write_idx + CLDFB_NO_COL_MAX ) % hSpatParamRendCom->dirac_md_buffer_length; + hDirAC->spar_to_dirac_write_idx = ( hDirAC->spar_to_dirac_write_idx + CLDFB_NO_COL_MAX ) % hDirAC->dirac_md_buffer_length; } } else diff --git a/lib_dec/ivas_stat_dec.h b/lib_dec/ivas_stat_dec.h index 5c70409ac2892ff9da3cd11cb968662475c17784..d5144018e5589464eef85fb06621a2aea303851b 100644 --- a/lib_dec/ivas_stat_dec.h +++ b/lib_dec/ivas_stat_dec.h @@ -396,9 +396,40 @@ typedef struct } ISM_DTX_DATA_DEC; /*----------------------------------------------------------------------------------* - * DirAC decoder structures + * DirAC decoder structure *----------------------------------------------------------------------------------*/ +typedef struct dirac_dec_stack_mem +{ + /*Decorrelator*/ + float *frame_dec_f; + + /*Prototypes*/ + float *proto_direct_buffer_f; + float *proto_diffuse_buffer_f; + + /*Prototype NRGs*/ + float *proto_power_smooth; + float *proto_power_diff_smooth; + + /*Gain or power factors for directional and diffuse streams*/ + float *direct_power_factor; + float *diffuse_power_factor; + + /*Directional responses (gains & Nrg)*/ + float *direct_responses; + float *direct_responses_square; + + /* Target co-variance mtx */ + float *cy_auto_dir_smooth; + float *cy_cross_dir_smooth; + float *cy_auto_diff_smooth; + + float *reference_power; + float *onset_filter; + +} DIRAC_DEC_STACK_MEM, *DIRAC_DEC_STACK_MEM_HANDLE; + typedef struct param_ism_rendering { float *proto_matrix; @@ -411,32 +442,115 @@ typedef struct param_ism_rendering } PARAM_ISM_RENDERING_DATA, *PARAM_ISM_RENDERING_HANDLE; -/* ===== DirAC main structure ===== */ -typedef struct ivas_dirac_dec_data_structure +/*Onset detector*/ +typedef struct dirac_onset_detection_params_structure { - DIRAC_CONFIG_DATA_HANDLE hConfig; + int16_t num_freq_bands; + int16_t max_band_decorr; - /*Parameter decoding*/ - float azimuth_values[MAX_PARAM_SPATIAL_SUBFRAMES * IVAS_MAX_NUM_BANDS]; - float elevation_values[MAX_PARAM_SPATIAL_SUBFRAMES * IVAS_MAX_NUM_BANDS]; - int16_t band_grouping[IVAS_MAX_NUM_BANDS + 1]; +} DIRAC_ONSET_DETECTION_PARAMS; - int16_t dithering_seed; - int16_t spar_to_dirac_write_idx; +typedef struct dirac_onset_detection_state_structure +{ + float *onset_detector_1; + float *onset_detector_2; - /*sub-modules*/ - PARAM_ISM_CONFIG_HANDLE hParamIsm; /* Parametric ISM handle */ - float power_ratios[MAX_PARAM_ISM_NBANDS][MAX_PARAM_ISM_NBLOCKS][MAX_PARAM_ISM_WAVE]; - PARAM_ISM_RENDERING_HANDLE hParamIsmRendering; +} DIRAC_ONSET_DETECTION_STATE; - IVAS_FB_MIXER_HANDLE hFbMdft; +/*Decorrelator*/ +typedef struct dirac_decorr_params_structure +{ + int16_t max_band_decorr; + int16_t max_frequency; -} DIRAC_DEC_DATA, *DIRAC_DEC_HANDLE; + int16_t *pre_delay; + int16_t *filter_length; + float *filter_coeff_num_real; + float *filter_coeff_den_real; + float *phase_coeff_real; + float *phase_coeff_imag; + int16_t *split_frequency_bands; + int16_t num_split_frequency_bands; + int16_t use_ducker; + int16_t add_back_onsets_on; -/*----------------------------------------------------------------------------------* - * ParamMC structures - *----------------------------------------------------------------------------------*/ + DIRAC_ONSET_DETECTION_PARAMS h_onset_detection_power_params; + +} DIRAC_DECORR_PARAMS, *HANDLE_DIRAC_DECORR_PARAMS; + +typedef struct dirac_decorr_state_structure +{ + float *decorr_buffer; + float *direct_energy_smooth; + float *reverb_energy_smooth; + + DIRAC_ONSET_DETECTION_STATE h_onset_detection_power_state; + +} DIRAC_DECORR_STATE, *HANDLE_DIRAC_DECORR_STATE; + +/*Output synthesis*/ +typedef struct dirac_output_synthesis_params_structure +{ + int16_t max_band_decorr; + + int16_t use_onset_filters; + + float *interpolator; + float *alpha_synthesis; + float *alpha_synthesis_fast; + int16_t numAlphas; + int16_t numAlphasFast; + + float *proto_matrix; + + float diffuse_compensation_factor; + float diffuse_compensation_factor_decorr; + +} DIRAC_OUTPUT_SYNTHESIS_PARAMS; + +typedef struct dirac_output_synthesis_state_structure +{ + /* only pointer to local buffers */ + float *direct_responses; /* direct responses for DOA of current frame. Size: num_freq_bands*num_channels. */ + float *direct_responses_square; + float *diffuse_responses_square; /* squared diffuse responses. Size: num_channels. */ + + /* only pointer to local buffers */ + float *direct_power_factor; + float *diffuse_power_factor; + + float *proto_power_smooth; /* Smoothed power of the prototype signals. Size: num_freq_bands*num_channels. */ + float *proto_power_smooth_prev; /* Smoothed power of the prototype signals of the previous synthesis block. Size: num_freq_bands*num_channels. */ + + float *proto_power_diff_smooth; + float *proto_power_diff_smooth_prev; + + /* only pointer to local buffers */ + float *proto_direct_buffer_f; /* Buffer for direct sound prototype signals. Size: 2*num_freq_bands*num_channels*buffer_length (complex interleaved). */ + float *proto_diffuse_buffer_f; /* Buffer for diffuse sound prototype signals. Size: 2*num_freq_bands*num_channels*buffer_length (complex interleaved). */ + + /* Output gain memories */ + float *gains_dir_prev; /* Direct sound gains of current synthesis block. Size: num_freq_bands*num_channel. */ + float *gains_diff_prev; /* Diffuse sound gains of previous synthesis block. Size: num_freq_bands*num_channel. */ + + /* only pointer to local buffers */ + float *cy_auto_dir_smooth; /* Target auto PSD of direct sound. Size: num_freq_bands*num_channels. */ + float *cy_cross_dir_smooth; /* Target cross PSD of direct sound. Size: num_freq_bands*num_channels. */ + float *cy_auto_diff_smooth; /* Target auto PSD of diffuse sound. Size: num_freq_bands*num_channels. */ + + /* PSD memories */ + float *cy_auto_dir_smooth_prev; /* Target auto PSD of direct sound of previous synthesis block. Size: num_freq_bands*num_channels. */ + float *cy_cross_dir_smooth_prev; /* Target cross PSD of direct sound of previous synthesis block. Size: num_freq_bands*num_channels. */ + float *cy_auto_diff_smooth_prev; /* Target auto PSD of diffuse sound of previous synthesis block. Size: num_freq_bands*num_channels. */ + + const float *onset_filter; + + /* Temporal smoothing memories */ + float *reference_power_smooth_prev; + float *direction_smoothness_prev; + +} DIRAC_OUTPUT_SYNTHESIS_STATE; typedef struct dirac_output_synthesis_cov_state_structure { @@ -465,6 +579,160 @@ typedef struct dirac_output_synthesis_cov_state_structure } DIRAC_OUTPUT_SYNTHESIS_COV_STATE; +/* MASA stereo transport signal type detection structure */ +typedef struct +{ + MASA_TRANSPORT_SIGNAL_TYPE masa_stereo_type; + MASA_TRANSPORT_SIGNAL_TYPE current_stereo_type; + MASA_TRANSPORT_SIGNAL_TYPE type_change_direction; + + int16_t dipole_freq_range[2]; + + float left_bb_power; + float right_bb_power; + float total_bb_power; + + float left_hi_power; + float right_hi_power; + float total_hi_power; + + float sum_power[MASA_SUM_FREQ_RANGE_BINS]; + float total_power[MASA_SUM_FREQ_RANGE_BINS]; + + float subtract_power_y; + float subtract_power_y_smooth; + float target_power_y_smooth; + + float lr_total_bb_ratio_db; + float lr_total_hi_ratio_db; + float min_sum_total_ratio_db; + float subtract_target_ratio_db; + + int16_t counter; + int16_t interpolator; + +} MASA_STEREO_TYPE_DETECT; + +/* Diffuse sound directional distribution data structure */ +typedef struct ivas_diffuse_distribution_data_structure +{ + float diffuseRatioX[CLDFB_NO_CHANNELS_MAX]; + float diffuseRatioY[CLDFB_NO_CHANNELS_MAX]; + float diffuseRatioZ[CLDFB_NO_CHANNELS_MAX]; + +} DIFFUSE_DISTRIBUTION_DATA, *DIFFUSE_DISTRIBUTION_HANDLE; + + +/* ===== DirAC main structure ===== */ +typedef struct ivas_dirac_dec_data_structure +{ + DIRAC_CONFIG_DATA_HANDLE hConfig; + IVAS_OUTPUT_SETUP hOutSetup; + + int16_t slot_size; + int16_t subframe_nbslots[MAX_JBM_SUBFRAMES_5MS]; + int16_t subframes_rendered; + int16_t slots_rendered; + int16_t num_slots; + int16_t render_to_md_map[MAX_JBM_SUBFRAMES_5MS * JBM_CLDFB_SLOTS_IN_SUBFRAME]; + int16_t nb_subframes; + int16_t num_freq_bands; + + /*Parameter decoding*/ + float azimuth_values[MAX_PARAM_SPATIAL_SUBFRAMES * IVAS_MAX_NUM_BANDS]; + float elevation_values[MAX_PARAM_SPATIAL_SUBFRAMES * IVAS_MAX_NUM_BANDS]; + int16_t band_grouping[IVAS_MAX_NUM_BANDS + 1]; + + int16_t block_grouping[5]; + /* decoded, ungrouped and rounded values, we have 1 degree resolution anyway */ + int16_t **azimuth; + int16_t **elevation; + int16_t **azimuth2; + int16_t **elevation2; + + float **diffuseness_vector; + float **energy_ratio1; + float **energy_ratio2; + + float **spreadCoherence; + float **spreadCoherence2; + float **surroundingCoherence; + + int16_t dithering_seed; + int16_t dirac_bs_md_write_idx; + int16_t dirac_read_idx; + int16_t dirac_estimator_idx; + int16_t spar_to_dirac_write_idx; + int16_t dirac_md_buffer_length; + +#ifdef MASA_AND_OBJECTS + int16_t numSimultaneousDirections; /* From 1 to 2 + MAX_NUM_OBJECTS */ + int16_t numParametricDirections; /* 1 or 2 */ + int16_t numIsmDirections; /* From 0 to MAX_NUM_OBJECTS */ +#else + int16_t numSimultaneousDirections; /* 1 or 2 */ +#endif + DIFFUSE_DISTRIBUTION_HANDLE hDiffuseDist; + + /*Parameter estimation*/ + int16_t index_buffer_intensity; + float *buffer_intensity_real[DIRAC_NUM_DIMS][DIRAC_NO_COL_AVG_DIFF]; + float *buffer_energy; + + /*Decoder parameters */ + /*Prototypes*/ + int16_t num_outputs_dir; + int16_t num_outputs_diff; + int16_t num_protos_dir; + int16_t num_protos_diff; + int16_t num_protos_ambi; + DIRAC_SYNTHESIS_CONFIG synthesisConf; + DIRAC_PANNING_CONFIG panningConf; + + float *frequency_axis; + float *diffuse_response_function; + float *hoa_encoder; + const float *hoa_decoder; + + /*Options*/ + /* Decorrelator options */ + int16_t max_band_decorr; + + /* prototype computing */ + int16_t *proto_index_dir; + int16_t *proto_index_diff; + + int16_t proto_signal_decorr_on; + + /*Decoder states=memories*/ + float *proto_frame_f; + float *proto_frame_dec_f; + + DIRAC_DEC_STACK_MEM stack_mem; + MASA_STEREO_TYPE_DETECT *masa_stereo_type_detect; + + int16_t num_ele_spk_no_diffuse_rendering; + + /*sub-modules*/ + HANDLE_DIRAC_DECORR_PARAMS h_freq_domain_decorr_ap_params; + HANDLE_DIRAC_DECORR_STATE h_freq_domain_decorr_ap_state; + + DIRAC_OUTPUT_SYNTHESIS_PARAMS h_output_synthesis_psd_params; + DIRAC_OUTPUT_SYNTHESIS_STATE h_output_synthesis_psd_state; + + PARAM_ISM_CONFIG_HANDLE hParamIsm; /* Parametric ISM handle */ + float power_ratios[MAX_PARAM_ISM_NBANDS][MAX_PARAM_ISM_NBLOCKS][MAX_PARAM_ISM_WAVE]; + PARAM_ISM_RENDERING_HANDLE hParamIsmRendering; + IVAS_FB_MIXER_HANDLE hFbMdft; + const int16_t *sba_map_tc; + +} DIRAC_DEC_DATA, *DIRAC_DEC_HANDLE; + + +/*----------------------------------------------------------------------------------* + * ParamMC structures + *----------------------------------------------------------------------------------*/ + typedef struct ivas_param_mc_diff_proto_info_structure { int16_t num_protos_diff; @@ -715,6 +983,10 @@ typedef struct cpe_dec_data_structure float old_out_mdct[STEREO_MDCT2DFT_FADE_LEN_48k]; float old_outLB_mdct[2 * STEREO_MDCT2DFT_FADE_LEN_48k]; +#ifdef MASA_AND_OBJECTS + int32_t brate_surplus; /* bitrate surplus for bitrate adaptation in combined format coding */ +#endif + } CPE_DEC_DATA, *CPE_DEC_HANDLE; @@ -765,6 +1037,53 @@ typedef struct ivas_lfe_dec_data_structure } LFE_DEC_DATA, *LFE_DEC_HANDLE; +// Note: the following structures are used only in lib_dec but this would likely change in the future +/*----------------------------------------------------------------------------------* + * VBAP structures + *----------------------------------------------------------------------------------*/ + +/* Defines a single virtual surface triplet of loudspeakers + * with a precalculated inverse matrix */ +typedef struct vbap_vs_triplet_structure +{ + uint8_t speaker_node[3]; + float inverse_matrix[3][3]; + +} VBAP_VS_TRIPLET; + + +/* Storage structure for fast runtime triplet search */ +typedef struct triplet_search_structure +{ + VBAP_VS_TRIPLET *triplets; + int16_t num_triplets; + int16_t initial_search_indices[VBAP_NUM_SEARCH_SECTORS]; + +} VBAP_SEARCH_STRUCT; + + +/* VBAP data structure. Contains the formed virtual surface arrangement * and supporting data. */ +typedef struct vbap_data_structure +{ + VBAP_SEARCH_STRUCT search_struct[2]; /* Default to max two groups in this implementation */ + int16_t num_search_structs; + int16_t num_speaker_nodes; + int16_t num_speaker_nodes_internal; + int16_t top_virtual_speaker_node_index; /* These indices can be negative */ + int16_t bottom_virtual_speaker_node_index; + int16_t back_virtual_speaker_node_index; + float *bottom_virtual_speaker_node_division_gains; + float *top_virtual_speaker_node_division_gains; + float *back_virtual_speaker_node_division_gains; +#ifdef MASA_AND_OBJECTS + float *object_mode_bottom_virtual_speaker_node_division_gains; + float *object_mode_top_virtual_speaker_node_division_gains; + float *object_mode_back_virtual_speaker_node_division_gains; +#endif + +} VBAP_DATA, *VBAP_HANDLE; + + /*----------------------------------------------------------------------------------* * renderer structures *----------------------------------------------------------------------------------*/ @@ -809,6 +1128,39 @@ typedef struct ivas_binaural_rendering_struct * MASA decoder structures *----------------------------------------------------------------------------------*/ +/* McMASA LFE synthesis structure */ +typedef struct ivas_mcmasa_lfe_synth_struct +{ + float lfeToTotalEnergyRatio[MAX_PARAM_SPATIAL_SUBFRAMES]; + int16_t lfeGainPrevIndex; + float transportEneSmooth; + float protoLfeEneSmooth; + float targetEneLfeSmooth; + float targetEneTransSmooth; + + float *lfeSynthRingBuffer; + int16_t ringBufferLoPointer; + int16_t ringBufferHiPointer; + float lowpassSum; + int16_t ringBufferSize; + + float *lfeSynthRingBuffer2; + int16_t ringBufferLoPointer2; + float lowpassSum2; + int16_t ringBufferSize2; + + float *delayBuffer_syncLp; + int16_t delayBuffer_syncLp_size; + + float *delayBuffer_syncDirAC; + int16_t delayBuffer_syncDirAC_size; + + float lfeGainPrev; + float transportGainPrev; + float interpolator[CLDFB_NO_CHANNELS_MAX]; + +} MCMASA_LFE_SYNTH_DATA, *MCMASA_LFE_SYNTH_DATA_HANDLE; + typedef struct ivas_masa_decoder_ext_out_meta_struct { MASA_DECRIPTIVE_META descriptiveMeta; @@ -840,6 +1192,40 @@ typedef struct ivas_masa_decoder_struct } MASA_DECODER, *MASA_DECODER_HANDLE; +#ifdef MASA_AND_OBJECTS +/* Data structure for MASA_ISM rendering */ +typedef struct ivas_masa_ism_data_structure +{ + int16_t azimuth_ism[MAX_NUM_OBJECTS][MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR]; + int16_t elevation_ism[MAX_NUM_OBJECTS][MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR]; + float energy_ratio_ism[MAX_NUM_OBJECTS][MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR][CLDFB_NO_CHANNELS_MAX]; + + int16_t azimuth_ism_edited[MAX_NUM_OBJECTS]; + int16_t elevation_ism_edited[MAX_NUM_OBJECTS]; + uint8_t ism_is_edited[MAX_NUM_OBJECTS]; + + int16_t idx_separated_ism; + int16_t azimuth_separated_ism[MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR]; + int16_t elevation_separated_ism[MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR]; + + float q_azimuth_old[MAX_NUM_OBJECTS]; + float q_elevation_old[MAX_NUM_OBJECTS]; + + float ismPreprocMatrix[2][2][CLDFB_NO_CHANNELS_MAX]; + uint8_t objectsMoved; + float eneMoveIIR[2][CLDFB_NO_CHANNELS_MAX]; + float enePreserveIIR[2][CLDFB_NO_CHANNELS_MAX]; + float preprocEneTarget[CLDFB_NO_CHANNELS_MAX]; + float preprocEneRealized[CLDFB_NO_CHANNELS_MAX]; + + float **delayBuffer; + int16_t delayBuffer_size; + int16_t delayBuffer_nchan; + +} MASA_ISM_DATA, *MASA_ISM_DATA_HANDLE; +#endif + + /*----------------------------------------------------------------------------------* * Decoder configuration structure *----------------------------------------------------------------------------------*/ @@ -940,6 +1326,9 @@ typedef struct Decoder_Struct DECODER_CONFIG_HANDLE hDecoderConfig; /* Decoder configuration structure */ IVAS_FORMAT ivas_format; /* IVAS format */ +#ifdef MASA_AND_OBJECTS + IVAS_FORMAT last_ivas_format; /* last frame IVAS format */ +#endif int16_t sid_format; /* IVAS format indicator from SID frame */ int16_t nchan_transport; /* number of transport channels */ IVAS_OUTPUT_SETUP hOutSetup; /* output setup structure */ @@ -1011,11 +1400,19 @@ typedef struct Decoder_Struct float *hoa_dec_mtx; /* Pointer to decoder matrix for SBA */ HEAD_TRACK_DATA_HANDLE hHeadTrackData; /* Head tracking data structure */ RENDER_CONFIG_DATA *hRenderConfig; /* Renderer config pointer */ - int32_t binaural_latency_ns; /* Binauralization latency in ns */ + int32_t binaural_latency_ns; /* binauralization latency in ns */ +#ifdef MASA_AND_OBJECTS + MASA_ISM_DATA_HANDLE hMasaIsmData; /* MASA_ISM rendering structure */ EXTERNAL_ORIENTATION_HANDLE hExtOrientationData; /* External orientation data structure */ COMBINED_ORIENTATION_HANDLE hCombinedOrientationData; /* Combined external and head orientation data structure */ - DIRAC_REND_HANDLE hDirACRend; /* DirAC renderer handle */ - SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom; /* Spatial parametric (DirAC rend, ParamBin, ParamISM) rendering common data handle. */ + + uint8_t editing_ism_enabled; /* Todo Nokia: Temporary, used until proper ISM control available */ + int16_t index_of_edited_ism; /* Todo Nokia: Temporary, used until proper ISM control available */ + int16_t azimuth_edited; /* Todo Nokia: Temporary, used until proper ISM control available */ + int16_t elevation_edited; /* Todo Nokia: Temporary, used until proper ISM control available */ + + int16_t flag_omasa_brate; +#endif /* JBM module */ DECODER_TC_BUFFER_HANDLE hTcBuffer; /* JBM structure */ diff --git a/lib_dec/ivas_stereo_switching_dec.c b/lib_dec/ivas_stereo_switching_dec.c index 013cc24660264ccf974f7bd9529ca8de09dc9d46..4a4bb5ad14f8628091fe246ba98c932b0571c5ee 100644 --- a/lib_dec/ivas_stereo_switching_dec.c +++ b/lib_dec/ivas_stereo_switching_dec.c @@ -768,7 +768,11 @@ ivas_error stereo_memory_dec( if ( hCPE->hCoreCoder[0]->bfi == 0 ) { st = hCPE->hCoreCoder[1]; +#ifdef MASA_AND_OBJECTS + hCPE->hStereoTD->tdm_LRTD_flag = get_indice_st( hCPE->hCoreCoder[0], hCPE->element_brate + hCPE->brate_surplus, (int16_t) ( ( hCPE->element_brate / FRAMES_PER_SEC ) - nb_bits_metadata + ( hCPE->brate_surplus / FRAMES_PER_SEC ) - TDM_SECONDARY_SIGNALLING - TDM_RATIO_BITS - TDM_LP_REUSE_BITS - TDM_LR_CONTENT_BITS ), TDM_LR_CONTENT_BITS ); +#else hCPE->hStereoTD->tdm_LRTD_flag = get_indice_st( hCPE->hCoreCoder[0], hCPE->element_brate, (int16_t) ( ( hCPE->element_brate / FRAMES_PER_SEC ) - nb_bits_metadata - TDM_SECONDARY_SIGNALLING - TDM_RATIO_BITS - TDM_LP_REUSE_BITS - TDM_LR_CONTENT_BITS ), TDM_LR_CONTENT_BITS ); +#endif if ( hCPE->hStereoTD->tdm_LRTD_flag ) { @@ -876,7 +880,11 @@ ivas_error stereo_memory_dec( * Bitrate switching in MASA format *---------------------------------------------------------------*/ +#ifdef MASA_AND_OBJECTS + if ( ( ivas_format == MASA_FORMAT || ivas_format == MASA_ISM_FORMAT ) && nchan_transport == 2 ) +#else if ( ivas_format == MASA_FORMAT && nchan_transport == 2 ) +#endif { if ( hCPE->nchan_out == 1 ) { diff --git a/lib_dec/ivas_stereo_td_dec.c b/lib_dec/ivas_stereo_td_dec.c index 605d5ad388ca0f2bf6853c8deb59ac9cd881762d..3b654960c18af14a7a869041da48af43b155a000 100644 --- a/lib_dec/ivas_stereo_td_dec.c +++ b/lib_dec/ivas_stereo_td_dec.c @@ -84,6 +84,10 @@ void stereo_td_init_dec( *-------------------------------------------------------------------*/ void tdm_configure_dec( +#ifdef MASA_AND_OBJECTS + const int16_t ivas_format, /* i : IVAS format */ + const int16_t ism_mode, /* i : ISM mode in combined format */ +#endif CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */ int16_t *tdm_ratio_idx, /* o : ratio index */ const int16_t nb_bits_metadata /* i : number of metadata bits */ @@ -94,10 +98,19 @@ void tdm_configure_dec( int16_t tdm_tmp_SM_LRTD_flag; int16_t mod_ct, core, bits_offset; int16_t idx_LRTD_pri_side, tdm_inst_ratio_idx; +#ifdef MASA_AND_OBJECTS + int32_t element_brate_adapt; + int16_t bstr_last_pos; +#endif hStereoTD = hCPE->hStereoTD; sts = hCPE->hCoreCoder; +#ifdef MASA_AND_OBJECTS + element_brate_adapt = hCPE->element_brate + hCPE->brate_surplus; + bstr_last_pos = (int16_t) ( hCPE->element_brate / FRAMES_PER_SEC ) - nb_bits_metadata + (int16_t) ( hCPE->brate_surplus / FRAMES_PER_SEC ); +#endif + /*----------------------------------------------------------------* * Decode CoreCoder signaling *----------------------------------------------------------------*/ @@ -123,7 +136,11 @@ void tdm_configure_dec( /* Get few parameters needed to decode the bitrate allocated to each channel */ /* Get the coder_type of the secondary channel (last parameter on 2 bits) */ +#ifdef MASA_AND_OBJECTS + sts[1]->coder_type = get_indice_st( sts[0], element_brate_adapt, bstr_last_pos - TDM_SECONDARY_SIGNALLING, TDM_SECONDARY_SIGNALLING ); +#else sts[1]->coder_type = get_indice_st( sts[0], hCPE->element_brate, (int16_t) ( ( hCPE->element_brate / FRAMES_PER_SEC ) - nb_bits_metadata - TDM_SECONDARY_SIGNALLING ), TDM_SECONDARY_SIGNALLING ); +#endif /* Get the LRTD config flag: 1 = LRTD configuration, favor closer bitrate per channel; 0 = Pri/Sec configuration, bitrates linked wrt. the mono */ @@ -151,19 +168,31 @@ void tdm_configure_dec( *----------------------------------------------------------------*/ /* Get the correlation ratio */ +#ifdef MASA_AND_OBJECTS + *tdm_ratio_idx = get_indice_st( sts[0], element_brate_adapt, (int16_t) ( bstr_last_pos - TDM_SECONDARY_SIGNALLING - TDM_RATIO_BITS ), TDM_RATIO_BITS ); +#else *tdm_ratio_idx = get_indice_st( sts[0], hCPE->element_brate, (int16_t) ( ( hCPE->element_brate / FRAMES_PER_SEC ) - nb_bits_metadata - TDM_SECONDARY_SIGNALLING - TDM_RATIO_BITS ), TDM_RATIO_BITS ); +#endif hStereoTD->tdm_use_IAWB_Ave_lpc = 0; if ( sts[1]->coder_type == INACTIVE ) { /* Get the flag on the LPC reusage type (primary channel of ave LPC */ +#ifdef MASA_AND_OBJECTS + hStereoTD->tdm_use_IAWB_Ave_lpc = get_indice_st( sts[0], element_brate_adapt, bstr_last_pos - TDM_SECONDARY_SIGNALLING - TDM_RATIO_BITS - TDM_LP_REUSE_BITS, TDM_LP_REUSE_BITS ); +#else hStereoTD->tdm_use_IAWB_Ave_lpc = get_indice_st( sts[0], hCPE->element_brate, (int16_t) ( ( hCPE->element_brate / FRAMES_PER_SEC ) - nb_bits_metadata - TDM_SECONDARY_SIGNALLING - TDM_RATIO_BITS - TDM_LP_REUSE_BITS ), TDM_LP_REUSE_BITS ); +#endif hStereoTD->tdm_lp_reuse_flag = 1; } else { /* Get the flag on the LPC reusage */ +#ifdef MASA_AND_OBJECTS + hStereoTD->tdm_lp_reuse_flag = get_indice_st( sts[0], element_brate_adapt, bstr_last_pos - TDM_SECONDARY_SIGNALLING - TDM_RATIO_BITS - TDM_LP_REUSE_BITS, TDM_LP_REUSE_BITS ); +#else hStereoTD->tdm_lp_reuse_flag = get_indice_st( sts[0], hCPE->element_brate, (int16_t) ( ( hCPE->element_brate / FRAMES_PER_SEC ) - nb_bits_metadata - TDM_SECONDARY_SIGNALLING - TDM_RATIO_BITS - TDM_LP_REUSE_BITS ), TDM_LP_REUSE_BITS ); +#endif } sts[0]->tdm_LRTD_flag = hStereoTD->tdm_LRTD_flag; /* the flag was already read in function stereo_memory_dec() */ @@ -219,7 +248,11 @@ void tdm_configure_dec( int16_t tmpS = 20; if ( hStereoTD->tdm_LRTD_flag == 0 ) { +#ifdef MASA_AND_OBJECTS + tmpS = get_indice_st( sts[0], element_brate_adapt, bstr_last_pos - TDM_SIGNAL_BITS_READ_FROM_THE_END_OF_BS + STEREO_BITS_TCA_CHAN + STEREO_BITS_TCA_CORRSTATS, STEREO_BITS_TCA_GD ); +#else tmpS = get_indice_st( sts[0], hCPE->element_brate, (int16_t) ( ( hCPE->element_brate / FRAMES_PER_SEC ) - nb_bits_metadata - TDM_SIGNAL_BITS_READ_FROM_THE_END_OF_BS + STEREO_BITS_TCA_CHAN + STEREO_BITS_TCA_CORRSTATS ), STEREO_BITS_TCA_GD ); +#endif } hCPE->hStereoDftDmx->targetGain = usdequant( tmpS, STEREO_TCA_GDMIN, STEREO_TCA_GDSTEP ); hCPE->hStereoDftDmx->targetGain = powf( 10, hCPE->hStereoDftDmx->targetGain ); @@ -228,9 +261,15 @@ void tdm_configure_dec( { if ( hStereoTD->tdm_LRTD_flag == 0 ) { +#ifdef MASA_AND_OBJECTS + hCPE->hStereoTCA->refChanIndx = get_indice_st( sts[0], element_brate_adapt, bstr_last_pos - TDM_SIGNAL_BITS_READ_FROM_THE_END_OF_BS, STEREO_BITS_TCA_CHAN ); + hCPE->hStereoTCA->indx_ica_NCShift = get_indice_st( sts[0], element_brate_adapt, bstr_last_pos - TDM_SIGNAL_BITS_READ_FROM_THE_END_OF_BS + STEREO_BITS_TCA_CHAN, STEREO_BITS_TCA_CORRSTATS ); + hCPE->hStereoTCA->indx_ica_gD = get_indice_st( sts[0], element_brate_adapt, bstr_last_pos - TDM_SIGNAL_BITS_READ_FROM_THE_END_OF_BS + STEREO_BITS_TCA_CHAN + STEREO_BITS_TCA_CORRSTATS, STEREO_BITS_TCA_GD ); +#else hCPE->hStereoTCA->refChanIndx = get_indice_st( sts[0], hCPE->element_brate, (int16_t) ( ( hCPE->element_brate / FRAMES_PER_SEC ) - nb_bits_metadata - TDM_SIGNAL_BITS_READ_FROM_THE_END_OF_BS ), STEREO_BITS_TCA_CHAN ); hCPE->hStereoTCA->indx_ica_NCShift = get_indice_st( sts[0], hCPE->element_brate, (int16_t) ( ( hCPE->element_brate / FRAMES_PER_SEC ) - nb_bits_metadata - TDM_SIGNAL_BITS_READ_FROM_THE_END_OF_BS + STEREO_BITS_TCA_CHAN ), STEREO_BITS_TCA_CORRSTATS ); hCPE->hStereoTCA->indx_ica_gD = get_indice_st( sts[0], hCPE->element_brate, (int16_t) ( ( hCPE->element_brate / FRAMES_PER_SEC ) - nb_bits_metadata - TDM_SIGNAL_BITS_READ_FROM_THE_END_OF_BS + STEREO_BITS_TCA_CHAN + STEREO_BITS_TCA_CORRSTATS ), STEREO_BITS_TCA_GD ); +#endif } else { @@ -250,7 +289,11 @@ void tdm_configure_dec( #endif /* set the BW of the secondary channel */ +#ifdef MASA_AND_OBJECTS + if ( hStereoTD->tdm_LRTD_flag && sts[1]->bits_frame_channel >= IVAS_16k4 / FRAMES_PER_SEC ) +#else if ( hStereoTD->tdm_LRTD_flag && hCPE->element_brate > IVAS_13k2 ) +#endif { /* set BW of the secondary channel in LRTD stereo mode as the BW of the primary channel at higher bitrates */ sts[1]->bwidth = sts[0]->bwidth; @@ -265,7 +308,16 @@ void tdm_configure_dec( * bitbudget distribution between channels (taking into account also metadata bitbudget) *----------------------------------------------------------------*/ +#ifdef MASA_AND_OBJECTS + tdm_bit_alloc( ivas_format, + ism_mode, + hCPE->element_brate - nb_bits_metadata * FRAMES_PER_SEC + hCPE->brate_surplus, + hStereoTD->tdm_lp_reuse_flag, &( sts[0]->total_brate ), &( sts[1]->total_brate ), + &hStereoTD->tdm_low_rate_mode, sts[1]->coder_type, *tdm_ratio_idx, hStereoTD->tdm_Pitch_reuse_flag, + sts[0]->bwidth, sts[1]->bwidth, sts[0]->flag_ACELP16k, hStereoTD->tdm_LRTD_flag, mod_ct, tdm_inst_ratio_idx ); +#else tdm_bit_alloc( hCPE->element_brate - nb_bits_metadata * FRAMES_PER_SEC, hStereoTD->tdm_lp_reuse_flag, &( sts[0]->total_brate ), &( sts[1]->total_brate ), &hStereoTD->tdm_low_rate_mode, sts[1]->coder_type, *tdm_ratio_idx, hStereoTD->tdm_Pitch_reuse_flag, sts[0]->bwidth, sts[1]->bwidth, sts[0]->flag_ACELP16k, hStereoTD->tdm_LRTD_flag, mod_ct, tdm_inst_ratio_idx ); +#endif return; } diff --git a/lib_dec/ivas_vbap.c b/lib_dec/ivas_vbap.c index 841f3df132015ea8ac0505bde28ffb4374ec315c..dcc73907e2942a0d7e348958203a59a924ce4130 100644 --- a/lib_dec/ivas_vbap.c +++ b/lib_dec/ivas_vbap.c @@ -141,7 +141,11 @@ static enum VirtualSpeakerNodeType check_need_of_virtual_speaker_node( VBAP_HAND static int16_t determine_best_triplet_and_gains( VBAP_SEARCH_STRUCT *search_struct, const float panning_unit_vec[3], const int16_t azi_deg, float gains[3] ); +#ifdef MASA_AND_OBJECTS +static void determine_virtual_speaker_node_division_gains( const int16_t virtual_speaker_node_index, float *virtual_node_division_gains, int16_t connections[][2], const enum VirtualSpeakerNodeType type, const int16_t max_num_connections, const int16_t num_speaker_nodes, const int16_t use_object_mode ); +#else static void determine_virtual_speaker_node_division_gains( const int16_t virtual_speaker_node_index, float *virtual_node_division_gains, int16_t connections[][2], const enum VirtualSpeakerNodeType type, const int16_t max_num_connections, const int16_t num_speaker_nodes ); +#endif static void reorder_triplets( VBAP_VS_TRIPLET *triplets, const int16_t *target_order, const int16_t num_triplets ); @@ -157,6 +161,10 @@ ivas_error vbap_init_data( const float *speaker_node_azi_deg, /* i : vector of speaker node azimuths (positive left) */ const float *speaker_node_ele_deg, /* i : vector of speaker node elevations (positive up) */ const int16_t num_speaker_nodes /* i : number of speaker nodes in the set */ +#ifdef MASA_AND_OBJECTS + , + const IVAS_FORMAT ivas_format /* i : IVAS format */ +#endif ) { /* Variables */ @@ -207,6 +215,11 @@ ivas_error vbap_init_data( vbap->bottom_virtual_speaker_node_division_gains = NULL; vbap->top_virtual_speaker_node_division_gains = NULL; vbap->back_virtual_speaker_node_division_gains = NULL; +#ifdef MASA_AND_OBJECTS + vbap->object_mode_bottom_virtual_speaker_node_division_gains = NULL; + vbap->object_mode_top_virtual_speaker_node_division_gains = NULL; + vbap->object_mode_back_virtual_speaker_node_division_gains = NULL; +#endif vbap->num_speaker_nodes = num_speaker_nodes; vbap->num_speaker_nodes_internal = num_speaker_nodes; @@ -229,6 +242,16 @@ ivas_error vbap_init_data( } set_zero( vbap->bottom_virtual_speaker_node_division_gains, num_speaker_nodes ); is_success &= vbap->bottom_virtual_speaker_node_division_gains != NULL; + +#ifdef MASA_AND_OBJECTS + if ( ivas_format == MASA_ISM_FORMAT ) + { + vbap->object_mode_bottom_virtual_speaker_node_division_gains = (float *) malloc( num_speaker_nodes * sizeof( float ) ); + set_zero( vbap->object_mode_bottom_virtual_speaker_node_division_gains, num_speaker_nodes ); + is_success &= vbap->object_mode_bottom_virtual_speaker_node_division_gains != NULL; + } +#endif + speaker_node_azi_deg_internal[vbap->bottom_virtual_speaker_node_index] = 0.0f; speaker_node_ele_deg_internal[vbap->bottom_virtual_speaker_node_index] = -90.0f; } @@ -241,6 +264,16 @@ ivas_error vbap_init_data( } set_zero( vbap->top_virtual_speaker_node_division_gains, num_speaker_nodes ); is_success &= vbap->top_virtual_speaker_node_division_gains != NULL; + +#ifdef MASA_AND_OBJECTS + if ( ivas_format == MASA_ISM_FORMAT ) + { + vbap->object_mode_top_virtual_speaker_node_division_gains = (float *) malloc( num_speaker_nodes * sizeof( float ) ); + set_zero( vbap->object_mode_top_virtual_speaker_node_division_gains, num_speaker_nodes ); + is_success &= vbap->object_mode_top_virtual_speaker_node_division_gains != NULL; + } +#endif + speaker_node_azi_deg_internal[vbap->top_virtual_speaker_node_index] = 0.0f; speaker_node_ele_deg_internal[vbap->top_virtual_speaker_node_index] = 90.0f; } @@ -253,6 +286,14 @@ ivas_error vbap_init_data( } set_zero( vbap->back_virtual_speaker_node_division_gains, num_speaker_nodes ); is_success &= vbap->back_virtual_speaker_node_division_gains != NULL; +#ifdef MASA_AND_OBJECTS + if ( ivas_format == MASA_ISM_FORMAT ) + { + vbap->object_mode_back_virtual_speaker_node_division_gains = (float *) malloc( num_speaker_nodes * sizeof( float ) ); + set_zero( vbap->object_mode_back_virtual_speaker_node_division_gains, num_speaker_nodes ); + is_success &= vbap->object_mode_back_virtual_speaker_node_division_gains != NULL; + } +#endif speaker_node_azi_deg_internal[vbap->back_virtual_speaker_node_index] = 180.0f; speaker_node_ele_deg_internal[vbap->back_virtual_speaker_node_index] = 0.0f; } @@ -342,11 +383,23 @@ ivas_error vbap_init_data( /* Determine how the virtual node gains should be distributed to real nodes, if necessary (checked within function). */ if ( is_success ) { +#ifdef MASA_AND_OBJECTS + determine_virtual_speaker_node_division_gains( vbap->top_virtual_speaker_node_index, vbap->top_virtual_speaker_node_division_gains, connections, virtual_top_type, max_num_connections, num_speaker_nodes, 0 ); + determine_virtual_speaker_node_division_gains( vbap->bottom_virtual_speaker_node_index, vbap->bottom_virtual_speaker_node_division_gains, connections, virtual_bottom_type, max_num_connections, num_speaker_nodes, 0 ); + determine_virtual_speaker_node_division_gains( vbap->back_virtual_speaker_node_index, vbap->back_virtual_speaker_node_division_gains, connections, virtual_back_type, max_num_connections, num_speaker_nodes, 0 ); + if ( ivas_format == MASA_ISM_FORMAT ) + { + determine_virtual_speaker_node_division_gains( vbap->top_virtual_speaker_node_index, vbap->object_mode_top_virtual_speaker_node_division_gains, connections, virtual_top_type == NO_VIRTUAL_SPEAKER_NODE ? NO_VIRTUAL_SPEAKER_NODE : VIRTUAL_SPEAKER_NODE_DISTRIBUTE_ENERGY, max_num_connections, num_speaker_nodes, 1 ); + determine_virtual_speaker_node_division_gains( vbap->bottom_virtual_speaker_node_index, vbap->object_mode_bottom_virtual_speaker_node_division_gains, connections, virtual_bottom_type == NO_VIRTUAL_SPEAKER_NODE ? NO_VIRTUAL_SPEAKER_NODE : VIRTUAL_SPEAKER_NODE_DISTRIBUTE_ENERGY, max_num_connections, num_speaker_nodes, 1 ); + determine_virtual_speaker_node_division_gains( vbap->back_virtual_speaker_node_index, vbap->object_mode_back_virtual_speaker_node_division_gains, connections, virtual_back_type == NO_VIRTUAL_SPEAKER_NODE ? NO_VIRTUAL_SPEAKER_NODE : VIRTUAL_SPEAKER_NODE_DISTRIBUTE_ENERGY, max_num_connections, num_speaker_nodes, 1 ); + } +#else determine_virtual_speaker_node_division_gains( vbap->top_virtual_speaker_node_index, vbap->top_virtual_speaker_node_division_gains, connections, virtual_top_type, max_num_connections, num_speaker_nodes ); determine_virtual_speaker_node_division_gains( vbap->bottom_virtual_speaker_node_index, vbap->bottom_virtual_speaker_node_division_gains, connections, virtual_bottom_type, max_num_connections, num_speaker_nodes ); determine_virtual_speaker_node_division_gains( vbap->back_virtual_speaker_node_index, vbap->back_virtual_speaker_node_division_gains, connections, virtual_back_type, max_num_connections, num_speaker_nodes ); +#endif } pop_wmops(); @@ -391,6 +444,20 @@ void vbap_free_data( { free( ( *hVBAPdata )->back_virtual_speaker_node_division_gains ); } +#ifdef MASA_AND_OBJECTS + if ( ( *hVBAPdata )->object_mode_bottom_virtual_speaker_node_division_gains != NULL ) + { + free( ( *hVBAPdata )->object_mode_bottom_virtual_speaker_node_division_gains ); + } + if ( ( *hVBAPdata )->object_mode_top_virtual_speaker_node_division_gains != NULL ) + { + free( ( *hVBAPdata )->object_mode_top_virtual_speaker_node_division_gains ); + } + if ( ( *hVBAPdata )->object_mode_back_virtual_speaker_node_division_gains != NULL ) + { + free( ( *hVBAPdata )->object_mode_back_virtual_speaker_node_division_gains ); + } +#endif if ( ( *hVBAPdata )->search_struct[0].triplets != NULL ) { free( ( *hVBAPdata )->search_struct[0].triplets ); @@ -418,6 +485,10 @@ void vbap_determine_gains( float *gains, /* o : gain vector for loudspeakers for given direction */ const int16_t azi_deg, /* i : azimuth in degrees for panning direction (positive left)*/ const int16_t ele_deg /* i : elevation in degrees for panning direction (positive up)*/ +#ifdef MASA_AND_OBJECTS + , + const int16_t use_object_mode /* i : select between object mode panning and spatial mode panning */ +#endif ) { /* This function formulates gains for the given angle. The triplet-selection has been pre-formulated. */ @@ -451,9 +522,24 @@ void vbap_determine_gains( bottom_virtual_speaker_node_index = hVBAPdata->bottom_virtual_speaker_node_index; top_virtual_speaker_node_index = hVBAPdata->top_virtual_speaker_node_index; back_virtual_speaker_node_index = hVBAPdata->back_virtual_speaker_node_index; +#ifdef MASA_AND_OBJECTS + if ( use_object_mode ) + { + bottom_virtual_speaker_node_division_gains = hVBAPdata->object_mode_bottom_virtual_speaker_node_division_gains; + top_virtual_speaker_node_division_gains = hVBAPdata->object_mode_top_virtual_speaker_node_division_gains; + back_virtual_speaker_node_division_gains = hVBAPdata->object_mode_back_virtual_speaker_node_division_gains; + } + else + { + bottom_virtual_speaker_node_division_gains = hVBAPdata->bottom_virtual_speaker_node_division_gains; + top_virtual_speaker_node_division_gains = hVBAPdata->top_virtual_speaker_node_division_gains; + back_virtual_speaker_node_division_gains = hVBAPdata->back_virtual_speaker_node_division_gains; + } +#else bottom_virtual_speaker_node_division_gains = hVBAPdata->bottom_virtual_speaker_node_division_gains; top_virtual_speaker_node_division_gains = hVBAPdata->top_virtual_speaker_node_division_gains; back_virtual_speaker_node_division_gains = hVBAPdata->back_virtual_speaker_node_division_gains; +#endif panning_wrap_angles( (float) azi_deg, (float) ele_deg, &azi_temp, &ele_temp ); azi_rad = azi_temp * PI_OVER_180; @@ -702,6 +788,10 @@ static void determine_virtual_speaker_node_division_gains( const enum VirtualSpeakerNodeType type, /* i : virtual speaker node typel */ const int16_t max_num_connections, /* i : max number of connections */ const int16_t num_speaker_nodes /* i : max number of speaker nodes */ +#ifdef MASA_AND_OBJECTS + , + const int16_t use_object_mode /* i : use VBAP in object panning mode vs. spatial panning mode */ +#endif ) { /* When node type is VIRTUAL_SPEAKER_NODE_DISTRIBUTE_ENERGY, the gains of the virtual node @@ -744,6 +834,12 @@ static void determine_virtual_speaker_node_division_gains( for ( ch = 0; ch < num_speaker_nodes; ch++ ) { virtual_node_division_gains[ch] /= sum_val; +#ifdef MASA_AND_OBJECTS + if ( use_object_mode ) + { + virtual_node_division_gains[ch] = powf( virtual_node_division_gains[ch], 0.8f ); + } +#endif } } diff --git a/lib_dec/lib_dec.c b/lib_dec/lib_dec.c index 686a4b6da76eec1610cc50c681c95b682f7114f1..470ed95f1aa5653f6caf3dfbb59ceb45f28b2999 100644 --- a/lib_dec/lib_dec.c +++ b/lib_dec/lib_dec.c @@ -214,6 +214,13 @@ ivas_error IVAS_DEC_Open( st_ivas->sba_planar = 0; st_ivas->sba_analysis_order = 0; +#ifdef MASA_AND_OBJECTS + hIvasDec->st_ivas->editing_ism_enabled = 0; + hIvasDec->st_ivas->index_of_edited_ism = 0; + hIvasDec->st_ivas->azimuth_edited = 0; + hIvasDec->st_ivas->elevation_edited = 0; +#endif + return IVAS_ERR_OK; } @@ -401,6 +408,10 @@ static IVAS_DEC_BS_FORMAT mapIvasFormat( return IVAS_DEC_BS_SBA; case MASA_FORMAT: return IVAS_DEC_BS_MASA; +#ifdef OMASA_EXT_OUTPUT + case MASA_ISM_FORMAT: + return IVAS_DEC_BS_MASA_ISM; +#endif default: break; } @@ -996,9 +1007,17 @@ ivas_error IVAS_DEC_GetNumObjects( return IVAS_ERR_UNEXPECTED_NULL_POINTER; } +#ifdef OMASA_EXT_OUTPUT + if ( hIvasDec->st_ivas->ivas_format == ISM_FORMAT || hIvasDec->st_ivas->ivas_format == MASA_ISM_FORMAT ) +#else if ( hIvasDec->st_ivas->ivas_format == ISM_FORMAT ) +#endif { +#ifdef OMASA_EXT_OUTPUT + *numObjects = hIvasDec->st_ivas->nchan_ism; +#else *numObjects = hIvasDec->st_ivas->hDecoderConfig->nchan_out; +#endif } else { @@ -1081,12 +1100,20 @@ ivas_error IVAS_DEC_GetObjectMetadata( st_ivas = hIvasDec->st_ivas; +#ifdef OMASA_EXT_OUTPUT + if ( st_ivas->ivas_format != ISM_FORMAT && st_ivas->ivas_format != MASA_ISM_FORMAT ) +#else if ( st_ivas->ivas_format != ISM_FORMAT ) +#endif { return IVAS_ERR_WRONG_MODE; } +#ifdef OMASA_EXT_OUTPUT + if ( objectIdx >= st_ivas->nchan_ism ) +#else if ( objectIdx >= st_ivas->hDecoderConfig->nchan_out ) +#endif { return IVAS_ERR_INVALID_INDEX; } @@ -1142,7 +1169,11 @@ ivas_error IVAS_DEC_GetMasaMetadata( return IVAS_ERR_UNEXPECTED_NULL_POINTER; } +#ifdef OMASA_EXT_OUTPUT + if ( hIvasDec->st_ivas->ivas_format != MASA_FORMAT && hIvasDec->st_ivas->ivas_format != MASA_ISM_FORMAT ) +#else if ( hIvasDec->st_ivas->ivas_format != MASA_FORMAT ) +#endif { return IVAS_ERR_WRONG_MODE; } @@ -1195,6 +1226,11 @@ ivas_error IVAS_DEC_FeedHeadTrackData( { /* check for Euler angle signaling */ #ifdef SPLIT_REND_WITH_HEAD_ROT +#ifndef EULER2QUAT_FIX + /* TODO: temp change until Euler2Quat() is fixed*/ + if ( ( hIvasDec->st_ivas->hDecoderConfig->output_config != AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) && + ( hIvasDec->st_ivas->hDecoderConfig->output_config != AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) +#endif #endif { if ( orientation[i].w == -3.0f ) @@ -1402,7 +1438,7 @@ ivas_error IVAS_DEC_GetHrtfHandle( ivas_error IVAS_DEC_GetHrtfCRendHandle( IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ - IVAS_DEC_HRTF_CREND_HANDLE *hSetOfHRTF /* o : Set of HRTF handle */ + IVAS_DEC_HRTF_CREND_HANDLE *hSetOfHRTF /* o : Set of HRTF handle */ ) { if ( hIvasDec == NULL || hIvasDec->st_ivas == NULL || hIvasDec->st_ivas->hSetOfHRTF == NULL ) @@ -1415,6 +1451,36 @@ ivas_error IVAS_DEC_GetHrtfCRendHandle( return IVAS_ERR_OK; } + +#ifdef MASAISM_EDIT_OBJECTS +/*---------------------------------------------------------------------* + * IVAS_DEC_SetEditedIsmPositions( ) + * + * + *---------------------------------------------------------------------*/ + +ivas_error IVAS_DEC_SetEditedIsmPositions( + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + int16_t index_of_edited_ism, /* i : Index of edited ISM */ + int16_t azimuth_edited_ism, /* i : Azimuth */ + int16_t elevation_edited_ism /* i : Elevation */ +) +{ + if ( hIvasDec == NULL || hIvasDec->st_ivas == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + hIvasDec->st_ivas->editing_ism_enabled = 1; + hIvasDec->st_ivas->index_of_edited_ism = index_of_edited_ism; + hIvasDec->st_ivas->azimuth_edited = azimuth_edited_ism; + hIvasDec->st_ivas->elevation_edited = elevation_edited_ism; + + return IVAS_ERR_OK; +} +#endif + + /*---------------------------------------------------------------------* * IVAS_DEC_GetHrtfFastConvHandle( ) * @@ -1422,8 +1488,8 @@ ivas_error IVAS_DEC_GetHrtfCRendHandle( *---------------------------------------------------------------------*/ ivas_error IVAS_DEC_GetHrtfFastConvHandle( - IVAS_DEC_HANDLE hIvasDec, /* i/oL IVAS decoder handle */ - IVAS_DEC_HRTF_FASTCONV_HANDLE *hHrtfFastConv /* o : FASTCONV HRTF handle */ + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + IVAS_DEC_HRTF_FASTCONV_HANDLE *hHrtfFastConv /* o : FASTCONV HRTF handle */ ) { if ( hIvasDec == NULL || hIvasDec->st_ivas == NULL || hIvasDec->st_ivas->hHrtfFastConv == NULL ) @@ -1436,6 +1502,7 @@ ivas_error IVAS_DEC_GetHrtfFastConvHandle( return IVAS_ERR_OK; } + /*---------------------------------------------------------------------* * IVAS_DEC_GetHrtfParamBinHandle( ) * @@ -1457,6 +1524,7 @@ ivas_error IVAS_DEC_GetHrtfParamBinHandle( return IVAS_ERR_OK; } + /*---------------------------------------------------------------------* * IVAS_DEC_GetRenderConfig( ) * @@ -2615,7 +2683,11 @@ static ivas_error printConfigInfo_dec( { fprintf( stdout, "Input configuration: MASA - %d channel(s)\n", st_ivas->nchan_transport ); } +#ifdef MASA_AND_OBJECTS + else if ( st_ivas->ivas_format == MC_FORMAT ) +#else else /* MC_FORMAT */ +#endif { if ( ( error = get_channel_config( st_ivas->transport_config, &config_str[0] ) ) != IVAS_ERR_OK ) { @@ -2624,6 +2696,12 @@ static ivas_error printConfigInfo_dec( fprintf( stdout, "Input configuration: %s\n", config_str ); } +#ifdef MASA_AND_OBJECTS + else if ( st_ivas->ivas_format == MASA_ISM_FORMAT ) + { + fprintf( stdout, "Input configuration: combined ISM and MASA (%i ISM stream(s)) \n", st_ivas->nchan_ism ); + } +#endif } get_channel_config( st_ivas->hDecoderConfig->output_config, &config_str[0] ); diff --git a/lib_dec/lib_dec.h b/lib_dec/lib_dec.h index 9edc1a130c0bb520db9e529fd779361a263c5940..e214796629901515ee5d6496552f608329012639 100644 --- a/lib_dec/lib_dec.h +++ b/lib_dec/lib_dec.h @@ -116,6 +116,9 @@ typedef enum _IVAS_DEC_BS_FORMAT IVAS_DEC_BS_SBA, IVAS_DEC_BS_OBJ, IVAS_DEC_BS_MASA, +#ifdef OMASA_EXT_OUTPUT + IVAS_DEC_BS_MASA_ISM, +#endif IVAS_DEC_BS_UNKOWN = 0xffff } IVAS_DEC_BS_FORMAT; @@ -358,15 +361,24 @@ ivas_error IVAS_DEC_GetHrtfCRendHandle( ); ivas_error IVAS_DEC_GetHrtfFastConvHandle( - IVAS_DEC_HANDLE hIvasDec, /* i/oL IVAS decoder handle */ - IVAS_DEC_HRTF_FASTCONV_HANDLE *hHrtfFastConv /* o : FASTCONV HRTF handle */ + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + IVAS_DEC_HRTF_FASTCONV_HANDLE *hHrtfFastConv /* o : FASTCONV HRTF handle */ ); ivas_error IVAS_DEC_GetHrtfParamBinHandle( - IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ - IVAS_DEC_HRTF_PARAMBIN_HANDLE *hHrtfParambin /* o : Parametric binauralizer HRTF handle */ + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + IVAS_DEC_HRTF_PARAMBIN_HANDLE *hHrtfParambin /* o : Parametric binauralizer HRTF handle */ ); +#ifdef MASAISM_EDIT_OBJECTS +ivas_error IVAS_DEC_SetEditedIsmPositions( + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + int16_t index_of_edited_ism, /* i : Index of edited ISM */ + int16_t azimuth_edited_ism, /* i : Azimuth */ + int16_t elevation_edited_ism /* i : Elevation */ +); +#endif + /*! r: error code*/ ivas_error IVAS_DEC_GetRenderConfig( IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ diff --git a/lib_enc/bw_detect.c b/lib_enc/bw_detect.c index 121754e1dcd339c75a99d7fd76fd416faebfa8ae..e1e068ab2ca2a284939a38bb711d882866ca11e6 100644 --- a/lib_enc/bw_detect.c +++ b/lib_enc/bw_detect.c @@ -579,8 +579,12 @@ void set_bw( { st->bwidth = WB; } +#ifdef ISM_FB else if ( st->bwidth > SWB && ( ( element_brate < MIN_BRATE_FB_STEREO && !st->is_ism_format ) || ( element_brate < MIN_BRATE_FB_ISM && st->is_ism_format ) ) ) +#else + else if ( element_brate < MIN_BRATE_FB_STEREO && st->bwidth > SWB ) +#endif { st->bwidth = SWB; } diff --git a/lib_enc/ivas_core_enc.c b/lib_enc/ivas_core_enc.c index 7ff583a6d244e59ab05987986fe86f4510adc73d..bb750ffe77ac4069f2cd83d09df6b9494d31d6ea 100644 --- a/lib_enc/ivas_core_enc.c +++ b/lib_enc/ivas_core_enc.c @@ -102,6 +102,9 @@ ivas_error ivas_core_enc( float tdm_lspQ_PCh[M], tdm_lsfQ_PCh[M]; int16_t last_element_mode, tdm_Pitch_reuse_flag; int32_t element_brate, last_element_brate, input_Fs; +#ifdef MASA_AND_OBJECTS + int16_t diff_nBits; +#endif ivas_error error; int16_t max_num_indices_BWE; @@ -188,6 +191,18 @@ ivas_error ivas_core_enc( } } +#ifdef MASA_AND_OBJECTS + /*------------------------------------------------------------------* + * Sanity check in combined format coding + *-----------------------------------------------------------------*/ + + diff_nBits = 0; + if ( hCPE != NULL && hCPE->element_mode == IVAS_CPE_DFT && hCPE->brate_surplus > 0 ) + { + ivas_combined_format_brate_sanity( hCPE->element_brate, sts[0]->core, &( sts[0]->core_brate ), &diff_nBits ); + } +#endif + /*---------------------------------------------------------------------* * Core Encoding *---------------------------------------------------------------------*/ @@ -425,6 +440,22 @@ ivas_error ivas_core_enc( } } +#ifdef MASA_AND_OBJECTS + /*------------------------------------------------------------------* + * Write potentially unused bits in combined format coding + *-----------------------------------------------------------------*/ + + if ( hCPE != NULL && hCPE->element_mode == IVAS_CPE_DFT && hCPE->brate_surplus > 0 ) + { + while ( diff_nBits > 0 ) + { + n = min( diff_nBits, 16 ); + push_indice( sts[0]->hBstr, IND_UNUSED, 0, n ); + diff_nBits -= n; + } + } +#endif + #ifdef DEBUG_MODE_INFO for ( n = 0; n < n_CoreChannels; n++ ) { diff --git a/lib_enc/ivas_core_pre_proc_front.c b/lib_enc/ivas_core_pre_proc_front.c index 92c66f0de3a45a8fedce45a6eef569ef81f0e68b..20c2f164523ae396f77e29b1dab86b5eac69c8d2 100644 --- a/lib_enc/ivas_core_pre_proc_front.c +++ b/lib_enc/ivas_core_pre_proc_front.c @@ -161,6 +161,9 @@ ivas_error pre_proc_front_ivas( float temp1F_icatdmResampBuf[L_FILT_MAX]; /* temp buffers for ICA TDM resamplers */ int16_t old_pitch1; /* previous frame OL pitch[1] @12.8 kHz */ int16_t LR_localVAD; +#ifndef FIX_560_VAD_FLAG + int16_t LR_vad_flag; +#endif ivas_error error; push_wmops( "pre_proc_front" ); @@ -177,6 +180,9 @@ ivas_error pre_proc_front_ivas( res_cod_SNR_M = tmpF; LR_localVAD = 0; +#ifndef FIX_560_VAD_FLAG + LR_vad_flag = 0; +#endif if ( hSCE != NULL ) { @@ -204,6 +210,9 @@ ivas_error pre_proc_front_ivas( { /* Combine localVAD and vad_flag from LR processing */ LR_localVAD = hCPE->hCoreCoder[0]->localVAD || hCPE->hCoreCoder[1]->localVAD; +#ifndef FIX_560_VAD_FLAG + LR_vad_flag = hCPE->hFrontVad[0]->hVAD->vad_flag || hCPE->hFrontVad[1]->hVAD->vad_flag; +#endif } if ( hCPE->hStereoTD != NULL ) @@ -457,6 +466,10 @@ ivas_error pre_proc_front_ivas( /* Add down mix stereo activity to LR vad_flag_dtx */ *vad_flag_dtx = *vad_flag_dtx || st->vad_flag; +#ifndef FIX_560_VAD_FLAG + /* Combine the LR VAD flag and stereo downmix VAD flag */ + st->vad_flag = ( LR_vad_flag || st->vad_flag ); +#endif /* Determine hangover flag status based on LR localVAD and downmix localVAD */ *vad_hover_flag = *vad_flag_dtx && !( LR_localVAD || st->localVAD ); diff --git a/lib_enc/ivas_corecoder_enc_reconfig.c b/lib_enc/ivas_corecoder_enc_reconfig.c index ff79dd11b08269953be932ce5a9c57063a6fc52c..6f43073801eb2dcf7f69d0daefd2a99c23110f63 100644 --- a/lib_enc/ivas_corecoder_enc_reconfig.c +++ b/lib_enc/ivas_corecoder_enc_reconfig.c @@ -251,7 +251,7 @@ ivas_error ivas_corecoder_enc_reconfig( st_ivas->hCPE[0]->hStereoMdct = NULL; } - /* create missing core coder elements and set element bitrates for alrady existing ones */ + /* create missing core coder elements and set element bitrates for already existing ones */ if ( st_ivas->nSCE > 0 ) { nSCE_existing = min( nSCE_old, st_ivas->nSCE ); @@ -271,14 +271,22 @@ ivas_error ivas_corecoder_enc_reconfig( } /* propagate input audio buffers */ +#ifdef MASA_AND_OBJECTS + if ( n_CoreCoder_existing > sce_id && hEncoderConfig->ivas_format != MASA_ISM_FORMAT ) +#else if ( n_CoreCoder_existing > sce_id ) +#endif { mvr2r( input_buff[sce_id], st_ivas->hSCE[sce_id]->hCoreCoder[0]->input_buff, len_inp_memory ); } /* only reset indices if it is not the first index list, this already contains the IVAS format bits */ +#ifdef MASA_AND_OBJECTS + if ( sce_id > 0 || hEncoderConfig->ivas_format == MASA_ISM_FORMAT ) +#else if ( sce_id > 0 ) +#endif { reset_indices_enc( st_ivas->hSCE[sce_id]->hCoreCoder[0]->hBstr, st_ivas->hSCE[sce_id]->hCoreCoder[0]->hBstr->nb_ind_tot ); @@ -303,7 +311,13 @@ ivas_error ivas_corecoder_enc_reconfig( copy_encoder_config( st_ivas, st_ivas->hCPE[cpe_id]->hCoreCoder[n], 0 ); st_ivas->hCPE[cpe_id]->hCoreCoder[n]->total_brate = st_ivas->hCPE[cpe_id]->element_brate / ( st_ivas->nCPE > 1 ? 1 : CPE_CHANNELS ); /* dummy initialization for getting right pointers initialization of input buffers in init_coder_ace_plus() */ +#ifdef MASA_AND_OBJECTS + if ( ( cpe_id * CPE_CHANNELS + n > 0 ) || + ( st_ivas->mc_mode == MC_MODE_MCMASA && st_ivas->nSCE > 0 ) || + ( hEncoderConfig->ivas_format == MASA_ISM_FORMAT && st_ivas->nSCE > 0 ) ) +#else if ( cpe_id * CPE_CHANNELS + n > 0 || ( st_ivas->mc_mode == MC_MODE_MCMASA && st_ivas->nSCE > 0 ) ) +#endif { reset_indices_enc( st_ivas->hCPE[cpe_id]->hCoreCoder[n]->hBstr, st_ivas->hCPE[cpe_id]->hCoreCoder[n]->hBstr->nb_ind_tot ); diff --git a/lib_enc/ivas_cpe_enc.c b/lib_enc/ivas_cpe_enc.c index 09cd09eacc2c91991ed9f7362b3d03657dd4dcbb..e45949bbb2711e05ee4de0dd4310e2302bb14178 100644 --- a/lib_enc/ivas_cpe_enc.c +++ b/lib_enc/ivas_cpe_enc.c @@ -45,6 +45,15 @@ #include "wmc_auto.h" +#ifdef MASA_AND_OBJECTS +/*--------------------------------------------------------------------------* + * Local function prototypes + *--------------------------------------------------------------------------*/ + +static void stereo_mode_combined_format_enc( const Encoder_Struct *st_ivas, CPE_ENC_HANDLE hCPE ); +#endif + + /*-------------------------------------------------------------------* * ivas_cpe_enc() * @@ -101,6 +110,10 @@ ivas_error ivas_cpe_enc( ENCODER_CONFIG_HANDLE hEncoderConfig; int32_t ivas_total_brate; ivas_error error; +#ifdef MASA_AND_OBJECTS + int32_t cpe_brate; + int32_t element_brate_ref; +#endif error = IVAS_ERR_OK; @@ -113,6 +126,9 @@ ivas_error ivas_cpe_enc( ivas_format = hEncoderConfig->ivas_format; input_Fs = hEncoderConfig->input_Fs; ivas_total_brate = hEncoderConfig->ivas_total_brate; +#ifdef MASA_AND_OBJECTS + element_brate_ref = hCPE->element_brate; +#endif /*------------------------------------------------------------------* * Initialization - general @@ -168,6 +184,10 @@ ivas_error ivas_cpe_enc( hCPE->element_mode = select_stereo_mode( hCPE, ivas_format, ivas_total_brate ); } +#ifdef MASA_AND_OBJECTS + stereo_mode_combined_format_enc( st_ivas, hCPE ); +#endif + if ( ( error = front_vad( hCPE, NULL, hEncoderConfig, &hCPE->hFrontVad[0], st_ivas->hMCT != NULL, input_frame, vad_flag_dtx, fr_bands, Etot_LR, lf_E, localVAD_HE_SAD, vad_hover_flag, band_energies_LR, NULL, NULL ) ) != IVAS_ERR_OK ) { return error; @@ -193,6 +213,7 @@ ivas_error ivas_cpe_enc( return error; } + /*----------------------------------------------------------------* * Set TD stereo parameters *----------------------------------------------------------------*/ @@ -265,12 +286,28 @@ ivas_error ivas_cpe_enc( sts[n]->element_mode = hCPE->element_mode; } + if ( hCPE->element_mode != IVAS_CPE_MDCT && ( hCPE->element_brate != hCPE->last_element_brate || hCPE->last_element_mode != hCPE->element_mode || - sts[0]->ini_frame == 0 || sts[0]->last_core_brate <= SID_2k40 ) ) /* If the last frame was SID or NO_DATA, we need to run stereo_dft_config here since VAD decision is not known yet */ + sts[0]->ini_frame == 0 || +#ifdef MASA_AND_OBJECTS + ( ivas_total_brate != st_ivas->hEncoderConfig->last_ivas_total_brate ) || +#endif + sts[0]->last_core_brate <= SID_2k40 ) ) /* If the last frame was SID or NO_DATA, we need to run stereo_dft_config here since VAD decision is not known yet */ { if ( st_ivas->hQMetaData != NULL ) { - stereo_dft_config( hCPE->hStereoDft == NULL ? NULL : hCPE->hStereoDft->hConfig, st_ivas->hQMetaData->bits_frame_nominal * FRAMES_PER_SEC, &sts[0]->bits_frame_nominal, &sts[1]->bits_frame_nominal ); +#ifdef MASA_AND_OBJECTS + if ( ivas_format == MASA_ISM_FORMAT && st_ivas->ism_mode != ISM_MODE_NONE ) + { + stereo_dft_config( hCPE->hStereoDft == NULL ? NULL : hCPE->hStereoDft->hConfig, (int32_t) ( 0.70f * st_ivas->hQMetaData->bits_frame_nominal * FRAMES_PER_SEC ), &sts[0]->bits_frame_nominal, &sts[1]->bits_frame_nominal ); + } + else + { +#endif + stereo_dft_config( hCPE->hStereoDft == NULL ? NULL : hCPE->hStereoDft->hConfig, st_ivas->hQMetaData->bits_frame_nominal * FRAMES_PER_SEC, &sts[0]->bits_frame_nominal, &sts[1]->bits_frame_nominal ); +#ifdef MASA_AND_OBJECTS + } +#endif } else { @@ -294,6 +331,16 @@ ivas_error ivas_cpe_enc( if ( hCPE->element_mode == IVAS_CPE_MDCT ) { +#ifdef MASA_AND_OBJECTS + /* compute bit-rate surplus per channel in combined format coding */ + int32_t brate_surplus[CPE_CHANNELS]; + if ( st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_DISC ) + { + brate_surplus[0] = ( ( hCPE->brate_surplus / FRAMES_PER_SEC ) >> 1 ) * FRAMES_PER_SEC; + brate_surplus[1] = hCPE->brate_surplus - brate_surplus[0]; + } +#endif + /* this is just for initialization, the true values of "total_brate" and "bits_frame_channel" are set later */ for ( n = 0; n < n_CoreChannels; n++ ) { @@ -310,6 +357,15 @@ ivas_error ivas_cpe_enc( sts[n]->bits_frame_nominal = (int16_t) ( hCPE->element_brate / FRAMES_PER_SEC ); sts[n]->bits_frame_channel = (int16_t) ( ( hCPE->element_brate / FRAMES_PER_SEC ) / n_CoreChannels ); sts[n]->total_brate = hCPE->element_brate / n_CoreChannels; + +#ifdef MASA_AND_OBJECTS + /* subtract bit-rate for combined format coding */ + if ( st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_DISC ) + { + sts[n]->bits_frame_channel += (int16_t) ( brate_surplus[n] / FRAMES_PER_SEC ); + sts[n]->total_brate += brate_surplus[n]; + } +#endif } } @@ -356,7 +412,11 @@ ivas_error ivas_cpe_enc( else if ( hCPE->element_mode == IVAS_CPE_TD ) { /* Determine the energy ratio between the 2 channels */ - tdm_ratio_idx = stereo_tdm_ener_analysis( hCPE, input_frame, &tdm_SM_or_LRTD_Pri, &tdm_ratio_idx_SM ); + tdm_ratio_idx = stereo_tdm_ener_analysis( +#ifdef MASA_AND_OBJECTS + ivas_format, +#endif + hCPE, input_frame, &tdm_SM_or_LRTD_Pri, &tdm_ratio_idx_SM ); /* Compute the downmix signal based on the ratio index */ stereo_tdm_downmix( hCPE->hStereoTD, sts[0]->input, sts[1]->input, input_frame, tdm_ratio_idx, ( ( hCPE->hStereoTD->tdm_LRTD_flag == 0 ) ? tdm_SM_or_LRTD_Pri : 0 ), tdm_ratio_idx_SM ); @@ -364,6 +424,9 @@ ivas_error ivas_cpe_enc( /* signal the bitrate for BW selection in the SCh */ sts[0]->bits_frame_channel = 0; sts[1]->bits_frame_channel = (int16_t) ( hCPE->element_brate / FRAMES_PER_SEC ); +#ifdef MASA_AND_OBJECTS + sts[1]->bits_frame_channel += (int16_t) ( hCPE->brate_surplus / FRAMES_PER_SEC ); +#endif if ( st_ivas->hQMetaData != NULL ) { sts[1]->bits_frame_channel -= st_ivas->hQMetaData->metadata_max_bits; @@ -518,7 +581,12 @@ ivas_error ivas_cpe_enc( { tdm_ol_pitch_comparison( hCPE, pitch_fr, voicing_fr ); - tdm_configure_enc( hCPE, Etot_last, tdm_SM_or_LRTD_Pri, tdm_ratio_idx, tdm_ratio_idx_SM, attack_flag[0], nb_bits_metadata ); + tdm_configure_enc( +#ifdef MASA_AND_OBJECTS + ivas_format, + st_ivas->ism_mode, +#endif + hCPE, Etot_last, tdm_SM_or_LRTD_Pri, tdm_ratio_idx, tdm_ratio_idx_SM, attack_flag[0], nb_bits_metadata ); if ( hEncoderConfig->Opt_DTX_ON ) { @@ -550,6 +618,9 @@ ivas_error ivas_cpe_enc( * DFT Stereo parameters writing into the bitstream *----------------------------------------------------------------*/ +#ifdef MASA_AND_OBJECTS + cpe_brate = 0; +#endif if ( hCPE->element_mode == IVAS_CPE_DFT ) { if ( hEncoderConfig->Opt_DTX_ON ) @@ -578,6 +649,36 @@ ivas_error ivas_cpe_enc( } /* Write stereo bitstream */ +#ifdef MASA_AND_OBJECTS + cpe_brate = st_ivas->hCPE[0]->element_brate; + + /* DFT stereo side bits */ + if ( ( ivas_format == MASA_FORMAT || ivas_format == MASA_ISM_FORMAT ) && cpe_brate < MASA_STEREO_MIN_BITRATE && sts[0]->core_brate != SID_2k40 && sts[0]->core_brate != FRAME_NO_DATA ) + { + nb_bits = 0; /* Only mono downmix is transmitted in this case */ + } + else if ( ( ivas_format == MASA_FORMAT || ivas_format == MASA_ISM_FORMAT ) && ( sts[0]->core_brate == SID_2k40 || sts[0]->core_brate == FRAME_NO_DATA ) ) + { + nb_bits = hCPE->hMetaData->nb_bits_tot; + } + else + { + stereo_dft_enc_write_BS( hCPE, &nb_bits ); + } + + /* Residual coding in MDCT domain */ + if ( !( ( ivas_format == MASA_FORMAT || ivas_format == MASA_ISM_FORMAT ) && ( sts[0]->core_brate == SID_2k40 || sts[0]->core_brate == FRAME_NO_DATA ) ) ) + { + int16_t max_bits = (int16_t) ( hCPE->element_brate / FRAMES_PER_SEC - 0.8f * sts[0]->bits_frame_nominal ); + if ( ivas_format == MASA_FORMAT || ivas_format == MASA_ISM_FORMAT ) + { + max_bits -= nb_bits_metadata; + max_bits += (int16_t) ( hCPE->brate_surplus / FRAMES_PER_SEC ); + } + + stereo_dft_enc_res( hCPE->hStereoDft, old_inp_12k8[1] + L_INP_MEM - STEREO_DFT_OVL_8k, hCPE->hMetaData, &nb_bits, max_bits ); + } +#else if ( ivas_format == MASA_FORMAT && ivas_total_brate < MASA_STEREO_MIN_BITRATE && sts[0]->core_brate != SID_2k40 && sts[0]->core_brate != FRAME_NO_DATA ) { nb_bits = 0; /* Only mono downmix is transmitted in this case */ @@ -596,7 +697,7 @@ ivas_error ivas_cpe_enc( /* Residual coding in MDCT domain */ stereo_dft_enc_res( hCPE->hStereoDft, old_inp_12k8[1] + L_INP_MEM - STEREO_DFT_OVL_8k, hCPE->hMetaData, &nb_bits, (int16_t) ( ( hCPE->element_brate ) / FRAMES_PER_SEC - 0.8f * sts[0]->bits_frame_nominal - ( ( ivas_format == MASA_FORMAT ) ? nb_bits_metadata : 0 ) ) ); } - +#endif if ( sts[0]->core_brate == FRAME_NO_DATA || sts[0]->core_brate == SID_2k40 ) { assert( ( nb_bits <= ( ( IVAS_SID_5k2 - SID_2k40 ) / FRAMES_PER_SEC - SID_FORMAT_NBITS ) ) && "Stereo DFT CNG: bit budget is violated" ); @@ -611,8 +712,17 @@ ivas_error ivas_cpe_enc( /* subtract metadata bitbudget */ sts[0]->total_brate -= ( nb_bits_metadata * FRAMES_PER_SEC ); + +#ifdef MASA_AND_OBJECTS + /* subtract bit-rate for combined format coding */ + if ( ivas_format == MASA_ISM_FORMAT && ( st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_DISC ) ) + { + sts[0]->total_brate += hCPE->brate_surplus; + } +#endif } + /*----------------------------------------------------------------* * Core Encoder *----------------------------------------------------------------*/ @@ -629,6 +739,13 @@ ivas_error ivas_cpe_enc( hCPE->last_element_brate = hCPE->element_brate; hCPE->last_element_mode = hCPE->element_mode; +#ifdef MASA_AND_OBJECTS + if ( ivas_format == MASA_ISM_FORMAT ) + { + hCPE->element_brate = element_brate_ref; + } +#endif + if ( hCPE->element_mode == IVAS_CPE_MDCT && hCPE->hStereoMdct != NULL && hCPE->hStereoMdct->hItd != NULL ) { /* update input samples buffer */ @@ -672,7 +789,7 @@ ivas_error ivas_cpe_enc( dbgwrite( &n, 2, 1, input_frame, "res/TCA_idx_NCShift" ); dbgwrite( &n, 2, 1, input_frame, "res/TCA_idx_ica_gD" ); n = -1; - dbgwrite( &n, 2, 1, input_frame, "res/tdm_ratio_idx.enc" ); + // dbgwrite( &n, 2, 1, input_frame, "res/tdm_ratio_idx.enc" ); } else if ( hCPE->element_mode == IVAS_CPE_TD ) { @@ -689,7 +806,7 @@ ivas_error ivas_cpe_enc( else if ( hCPE->element_mode == IVAS_CPE_MDCT ) { n = -2; - dbgwrite( &n, 2, 1, input_frame, "res/tdm_ratio_idx.enc" ); + // dbgwrite( &n, 2, 1, input_frame, "res/tdm_ratio_idx.enc" ); } { @@ -762,13 +879,21 @@ ivas_error create_cpe_enc( hCPE->hFrontVad[0] = NULL; hCPE->hFrontVad[1] = NULL; +#ifdef MASA_AND_OBJECTS + hCPE->brate_surplus = 0; +#endif + /*-----------------------------------------------------------------* * Input memory buffer: allocate and initialize *-----------------------------------------------------------------*/ for ( n = 0; n < CPE_CHANNELS; n++ ) { +#ifdef MASA_AND_OBJECTS + if ( ivas_format == STEREO_FORMAT || ivas_format == MASA_FORMAT || ( ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCMASA ) || ivas_format == MASA_ISM_FORMAT ) +#else if ( ivas_format == STEREO_FORMAT || ivas_format == MASA_FORMAT || ( ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCMASA ) ) +#endif { if ( ( hCPE->input_mem[n] = (float *) malloc( sizeof( float ) * NS2SA( input_Fs, STEREO_DFT_OVL_NS ) ) ) == NULL ) { @@ -830,10 +955,17 @@ ivas_error create_cpe_enc( } copy_encoder_config( st_ivas, st, 1 ); + st->total_brate = hCPE->element_brate / ( st_ivas->nCPE > 1 ? 1 : CPE_CHANNELS ); /* dummy initialization for getting right pointers initialization of input buffers in init_coder_ace_plus() */ st->mct_chan_mode = MCT_CHAN_MODE_REGULAR; - if ( ( error = init_encoder( st, st_ivas, n, hEncoderConfig->var_SID_rate_flag, hEncoderConfig->interval_SID, 0, st_ivas->ism_mode ) ) != IVAS_ERR_OK ) + if ( ( error = init_encoder( st, st_ivas, n, hEncoderConfig->var_SID_rate_flag, hEncoderConfig->interval_SID, 0, +#ifdef MASA_AND_OBJECTS + ISM_MODE_NONE +#else + st_ivas->ism_mode +#endif + ) ) != IVAS_ERR_OK ) { return error; } @@ -1069,3 +1201,62 @@ void destroy_cpe_enc( return; } + + +#ifdef MASA_AND_OBJECTS +/*------------------------------------------------------------------------- + * stereo_mode_combined_format_enc() + * + * Set stereo format in a combined format + *-------------------------------------------------------------------------*/ + +static void stereo_mode_combined_format_enc( + const Encoder_Struct *st_ivas, /* i : encoder main structure */ + CPE_ENC_HANDLE hCPE /* i/o: CPE handle */ +) +{ + ENCODER_CONFIG_HANDLE hEncoderConfig; + int32_t element_brate_ref; + + hEncoderConfig = st_ivas->hEncoderConfig; + + if ( hEncoderConfig->ivas_format == MASA_ISM_FORMAT ) + { + element_brate_ref = hCPE->element_brate; + + if ( st_ivas->ism_mode == ISM_MASA_MODE_DISC && + ( ( hEncoderConfig->nchan_ism == 3 && hEncoderConfig->ivas_total_brate == IVAS_96k ) || + ( hEncoderConfig->nchan_ism == 4 && hEncoderConfig->ivas_total_brate == IVAS_128k ) ) ) + { + if ( hCPE->element_brate + hCPE->brate_surplus > IVAS_64k ) + { + st_ivas->hMasa->data.omasa_stereo_sw_cnt = 0; + } + else + { + st_ivas->hMasa->data.omasa_stereo_sw_cnt++; + st_ivas->hMasa->data.omasa_stereo_sw_cnt = min( st_ivas->hMasa->data.omasa_stereo_sw_cnt, OMASA_STEREO_SW_CNT_MAX ); + } + + if ( st_ivas->hMasa->data.omasa_stereo_sw_cnt < OMASA_STEREO_SW_CNT_MAX ) + { + hCPE->element_mode = IVAS_CPE_MDCT; + hCPE->element_brate = IVAS_64k; + hCPE->brate_surplus -= ( hCPE->element_brate - element_brate_ref ); + } + + /* write OMASA stereo mode signalling */ + if ( hCPE->element_mode == IVAS_CPE_MDCT ) + { + push_indice( hCPE->hCoreCoder[0]->hBstr, IND_SMODE_OMASA, 1, NBITS_ELEMENT_MODE ); + } + else + { + push_indice( hCPE->hCoreCoder[0]->hBstr, IND_SMODE_OMASA, 0, NBITS_ELEMENT_MODE ); + } + } + } + + return; +} +#endif diff --git a/lib_enc/ivas_decision_matrix_enc.c b/lib_enc/ivas_decision_matrix_enc.c index c731eeff02d171087bdcd50403fad4bda9c49a10..09d307e6244a774c9135b1c74f39cd6dd6b4a20e 100644 --- a/lib_enc/ivas_decision_matrix_enc.c +++ b/lib_enc/ivas_decision_matrix_enc.c @@ -164,6 +164,20 @@ void ivas_decision_matrix_enc( /* select TCX core or HQ core using bits_frame_nominal to match the TCX configuration bitrate */ st->core = mdct_classifier( st, fft_buff, enerBuffer, st->bits_frame_nominal * FRAMES_PER_SEC ); } + +#ifndef FIX_TCX_LOWRATE_LIMITATION + /* Warning: TCX not available at low bitrates -> replace it by GSC */ + if ( st->core == TCX_20_CORE && st->total_brate < STEREO_TCX_MIN_RATE ) + { + st->core = ACELP_CORE; + st->coder_type = AUDIO; + st->sp_aud_decision2 = 0; + if ( st->low_rate_mode ) + { + st->coder_type = INACTIVE; + } + } +#endif } /* do not allow TD stereo ACELP core -> DFT stereo TCX core switching as it is on the WC complexity path */ @@ -210,8 +224,23 @@ void ivas_decision_matrix_enc( } } +#ifndef FIX_TCX_LOWRATE_LIMITATION + /* TCX not available at low bitrates -> replace it by GSC */ + if ( st->core == TCX_20_CORE && st->total_brate < STEREO_TCX_MIN_RATE ) + { + st->core = ACELP_CORE; + st->coder_type = AUDIO; + st->sp_aud_decision2 = 0; + + if ( st->low_rate_mode ) + { + st->coder_type = INACTIVE; + } + } +#endif #endif +#ifdef FIX_TCX_LOWRATE_LIMITATION /* TCX not available at low bitrates -> replace it by GSC */ if ( st->core == TCX_20_CORE && st->total_brate < STEREO_TCX_MIN_RATE ) { @@ -224,6 +253,7 @@ void ivas_decision_matrix_enc( st->coder_type = INACTIVE; } } +#endif /*---------------------------------------------------------------------* * Select ACELP and GSC extension layer @@ -408,7 +438,11 @@ void ivas_signaling_enc( * Write element mode info *--------------------------------------------------------------------------*/ +#ifdef MASA_AND_OBJECTS + if ( ( st->element_mode == IVAS_CPE_DFT || st->element_mode == IVAS_CPE_TD ) && !MCT_flag ) /* note: in MCT, the MDCT stereo is used exclusively */ +#else if ( st->element_mode >= IVAS_CPE_DFT && element_brate < MIN_BRATE_MDCT_STEREO && !MCT_flag ) /* note: in MCT, the MDCT stereo is used exclusively */ +#endif { ind = st->element_mode - IVAS_CPE_DFT; push_indice( hBstr, IND_SMODE, ind, NBITS_ELEMENT_MODE ); @@ -423,8 +457,12 @@ void ivas_signaling_enc( { /* only WB is supported */ } +#ifdef ISM_FB else if ( ( element_brate < MIN_BRATE_FB_STEREO && !st->is_ism_format ) || ( element_brate < MIN_BRATE_FB_ISM && st->is_ism_format ) ) +#else + else if ( element_brate < MIN_BRATE_FB_STEREO ) +#endif { /* WB and SWB are supported */ ind = st->bwidth - WB; diff --git a/lib_enc/ivas_enc.c b/lib_enc/ivas_enc.c index 86d9dc3ec627e8ba6dc7f2ddbd5f8c660902ef70..10066a104ea8908ae9af596f0b3c8a0078718083 100644 --- a/lib_enc/ivas_enc.c +++ b/lib_enc/ivas_enc.c @@ -61,7 +61,11 @@ ivas_error ivas_enc( ENCODER_CONFIG_HANDLE hEncoderConfig; BSTR_ENC_HANDLE hMetaData; Encoder_State *st; /* used for bitstream handling */ +#ifdef MASA_AND_OBJECTS + int16_t nb_bits_metadata[MAX_SCE + 1]; +#else int16_t nb_bits_metadata[MAX_SCE]; +#endif float data_f[MAX_INPUT_CHANNELS][L_FRAME48k]; int32_t ivas_total_brate; ivas_error error; @@ -83,7 +87,11 @@ ivas_error ivas_enc( input_frame = (int16_t) ( input_Fs / FRAMES_PER_SEC ); n_samples_chan = n_samples / nchan_inp; +#ifdef MASA_AND_OBJECTS + set_s( nb_bits_metadata, 0, MAX_SCE + 1 ); +#else set_s( nb_bits_metadata, 0, MAX_SCE ); +#endif /*----------------------------------------------------------------* * convert 'short' input data to 'float' @@ -177,7 +185,12 @@ ivas_error ivas_enc( ivas_param_ism_stereo_dmx( st_ivas, data_f, input_frame ); /* Core coding of Stereo DMX */ - if ( ( error = ivas_ism_enc( st_ivas, data_f, input_frame, nb_bits_metadata ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_ism_enc( st_ivas, data_f, input_frame, nb_bits_metadata +#ifdef MASA_AND_OBJECTS + , + 0 +#endif + ) ) != IVAS_ERR_OK ) { return error; } @@ -185,7 +198,12 @@ ivas_error ivas_enc( else if ( st_ivas->ism_mode == ISM_MODE_DISC ) { /* Analysis, decision about bitrates per channel & core coding */ - if ( ( error = ivas_ism_enc( st_ivas, data_f, input_frame, nb_bits_metadata ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_ism_enc( st_ivas, data_f, input_frame, nb_bits_metadata +#ifdef MASA_AND_OBJECTS + , + 0 +#endif + ) ) != IVAS_ERR_OK ) { return error; } @@ -225,7 +243,12 @@ ivas_error ivas_enc( return error; } if ( ( error = ivas_masa_encode( st_ivas->hMasa, st_ivas->hQMetaData, hMetaData, &nb_bits_metadata[0], st_ivas->nchan_transport, ivas_format, - ivas_total_brate, hEncoderConfig->Opt_DTX_ON, st_ivas->nchan_transport == 2 ? st_ivas->hCPE[0]->element_mode : -1 ) ) != IVAS_ERR_OK ) + ivas_total_brate, hEncoderConfig->Opt_DTX_ON, st_ivas->nchan_transport == 2 ? st_ivas->hCPE[0]->element_mode : -1 +#ifdef MASA_AND_OBJECTS + , + ISM_MODE_NONE, -1, NULL, -1, NULL, 0, 0 +#endif + ) ) != IVAS_ERR_OK ) { return error; } @@ -266,18 +289,119 @@ ivas_error ivas_enc( } } } +#ifdef MASA_AND_OBJECTS + else if ( ivas_format == MASA_ISM_FORMAT ) + { + float data_separated_object[L_FRAME48k]; + int16_t idx_separated_object; + int16_t flag_omasa_ener_brate; + + flag_omasa_ener_brate = 0; + +#ifdef OMASA_FIX_LOW_FS + /* Estimate TF-tile energy for the input MASA stream */ + ivas_masa_estimate_energy( st_ivas->hMasa, &( data_f[hEncoderConfig->nchan_ism] ), input_frame, st_ivas->nchan_transport ); +#endif + + if ( ( error = ivas_omasa_enc_config( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* Stereo transport is used also with monoMASA, duplicate mono if monoMASA */ + if ( ( st_ivas->hEncoderConfig->nchan_inp - hEncoderConfig->nchan_ism ) == 1 ) + { + v_multc( data_f[hEncoderConfig->nchan_ism], 1.0f / SQRT2, data_f[hEncoderConfig->nchan_ism], input_frame ); + mvr2r( data_f[hEncoderConfig->nchan_ism], data_f[hEncoderConfig->nchan_ism + 1], input_frame ); + } + + set_s( nb_bits_metadata, 0, MAX_SCE + 1 ); + idx_separated_object = 0; + +#ifndef OMASA_FIX_LOW_FS + /* Estimate TF-tile energy for the input MASA stream */ + ivas_masa_estimate_energy( st_ivas->hMasa, &( data_f[hEncoderConfig->nchan_ism] ), input_frame, st_ivas->nchan_transport ); +#endif + + /* put audio object data in SCE's */ + if ( st_ivas->ism_mode != ISM_MASA_MODE_DISC ) + { + /* Estimate MASA parameters for the objects */ + ivas_omasa_enc( st_ivas->hOMasa, st_ivas->hMasa, st_ivas->hIsmMetaData, data_f, input_frame, st_ivas->nchan_transport, hEncoderConfig->nchan_ism, st_ivas->ism_mode, data_separated_object, &idx_separated_object ); + } + + /* Encode ISMs transport channels */ + n = 0; + if ( st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) + { + if ( ( error = ivas_sce_enc( st_ivas, 0, data_separated_object, input_frame, nb_bits_metadata[1] ) ) != IVAS_ERR_OK ) /* there are no metadata bits in SCE in this mode */ + { + return error; + } + } + else if ( st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) + { + if ( ( error = ivas_ism_enc( st_ivas, &data_separated_object, input_frame, &nb_bits_metadata[1], 0 ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else if ( st_ivas->ism_mode == ISM_MASA_MODE_DISC ) + { + flag_omasa_ener_brate = ivas_omasa_ener_brate( st_ivas->hEncoderConfig->nchan_ism, ivas_total_brate, data_f, input_frame ); + + /* Analysis, decision about bitrates per channel & core coding */ + if ( ( error = ivas_ism_enc( st_ivas, data_f, input_frame, &nb_bits_metadata[1], flag_omasa_ener_brate ) ) != IVAS_ERR_OK ) + { + return error; + } + n = st_ivas->hEncoderConfig->nchan_ism; + } + + hMetaData = st_ivas->hCPE[st_ivas->nCPE - 1]->hMetaData; + + if ( st_ivas->nSCE > 0 ) + { + /* update pointer to the buffer of indices (ISM indices were alredy written) */ + hMetaData->ind_list = st_ivas->hSCE[st_ivas->nSCE - 1]->hMetaData->ind_list + st_ivas->hSCE[st_ivas->nSCE - 1]->hMetaData->nb_ind_tot; + st_ivas->hCPE[0]->hCoreCoder[0]->hBstr->ind_list = st_ivas->hSCE[st_ivas->nSCE - 1]->hCoreCoder[0]->hBstr->ind_list + st_ivas->hSCE[st_ivas->nSCE - 1]->hCoreCoder[0]->hBstr->nb_ind_tot; + } + + /* Encode MASA parameters and write MASA metadata bitstream */ + if ( ( error = ivas_masa_encode( st_ivas->hMasa, st_ivas->hQMetaData, hMetaData, nb_bits_metadata, st_ivas->nchan_transport, ivas_format, ivas_total_brate, st_ivas->hEncoderConfig->Opt_DTX_ON, st_ivas->nchan_transport == 2 ? st_ivas->hCPE[0]->element_mode : -1, + st_ivas->ism_mode, hEncoderConfig->nchan_ism, st_ivas->hIsmMetaData, idx_separated_object, st_ivas->hOMasa, st_ivas->hIsmMetaData[0]->ism_imp, flag_omasa_ener_brate ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* Configuration of combined-format bit-budget distribution */ +#ifdef DEBUG_MODE_INFO + ivas_set_surplus_brate_enc( st_ivas, nb_bits_metadata ); +#else + ivas_set_surplus_brate_enc( st_ivas ); +#endif + + /* Encode MASA transport channels */ + if ( ( ivas_cpe_enc( st_ivas, 0, data_f[n], data_f[n + 1], input_frame, nb_bits_metadata[0] ) ) != IVAS_ERR_OK ) + { + return error; + } + } +#endif else if ( ivas_format == MC_FORMAT ) { /* select MC format mode; write MC LS setup; reconfigure the MC format encoder */ - if ( ( ivas_mc_enc_config( st_ivas ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_mc_enc_config( st_ivas ) ) != IVAS_ERR_OK ) { return error; } hMetaData = ( st_ivas->nSCE > 0 ) ? st_ivas->hSCE[st_ivas->nSCE - 1]->hMetaData : st_ivas->hCPE[st_ivas->nCPE - 1]->hMetaData; +#ifdef FIX_572_LFE_LPF_ENC /* LFE low pass filter */ ivas_lfe_lpf_enc_apply( st_ivas->hLfeLpf, data_f[LFE_CHANNEL], input_frame ); +#endif /* LFE channel encoder */ if ( st_ivas->mc_mode == MC_MODE_MCT ) @@ -336,7 +460,13 @@ ivas_error ivas_enc( ivas_mcmasa_enc( st_ivas->hMcMasa, st_ivas->hQMetaData, st_ivas->hMasa, data_f, input_frame, st_ivas->nchan_transport, nchan_inp ); - if ( ( error = ivas_masa_encode( st_ivas->hMasa, st_ivas->hQMetaData, hMetaData, &nb_bits_metadata[0], st_ivas->nchan_transport, ivas_format, ivas_total_brate, 0, -1 ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_masa_encode( st_ivas->hMasa, st_ivas->hQMetaData, hMetaData, &nb_bits_metadata[0], st_ivas->nchan_transport, ivas_format, ivas_total_brate, 0, -1 +#ifdef MASA_AND_OBJECTS + , + ISM_MODE_NONE, -1, NULL, -1, NULL, 0, 0 +#endif + + ) ) != IVAS_ERR_OK ) { return error; } diff --git a/lib_enc/ivas_init_enc.c b/lib_enc/ivas_init_enc.c index 6d0b1086c17dd9a7fea071165c24f7218ead2043..4b8801f7c3dc2449b566db6052932d7209409c93 100644 --- a/lib_enc/ivas_init_enc.c +++ b/lib_enc/ivas_init_enc.c @@ -37,6 +37,9 @@ #include "prot.h" #include "ivas_prot.h" #include "ivas_stat_enc.h" +#ifdef MASA_AND_OBJECTS +#include "ivas_rom_com.h" +#endif #ifdef DEBUGGING #include "debug.h" #endif @@ -83,6 +86,20 @@ void ivas_write_format( ind = 7; nBits += extra_bits; break; +#ifdef MASA_AND_OBJECTS + case MASA_ISM_FORMAT: + if ( st_ivas->ism_mode == ISM_MODE_NONE ) + { + ind = 7; /* send MASA format */ + nBits += extra_bits; + } + else + { + ind = 10; + nBits += extra_bits + IVAS_COMBINED_FORMAT_SIGNALLING_BITS; + } + break; +#endif default: assert( !"Invalid format. Aborting." ); break; @@ -161,7 +178,11 @@ void ivas_write_format_sid( ind = SID_MASA_2TC; } break; - +#ifdef MASA_AND_OBJECTS + case MASA_ISM_FORMAT: /* TODO Nokia: Finalize for SID case */ + ind = 8; + break; +#endif default: assert( !"Reserved SID format symbol written." ); break; @@ -203,7 +224,12 @@ int16_t getNumChanAnalysis( { n = st_ivas->hEncoderConfig->nchan_inp; } - +#ifdef MASA_AND_OBJECTS + else if ( st_ivas->hEncoderConfig->ivas_format == MASA_ISM_FORMAT ) + { + n = st_ivas->hEncoderConfig->nchan_inp; + } +#endif return n; } @@ -314,8 +340,15 @@ void ivas_initialize_handles_enc( /* LFE handle */ st_ivas->hLFE = NULL; +#ifdef FIX_572_LFE_LPF_ENC /* LFE low pass filter handle */ st_ivas->hLfeLpf = NULL; +#endif + +#ifdef MASA_AND_OBJECTS + /* Object MASA handle */ + st_ivas->hOMasa = NULL; +#endif return; } @@ -502,7 +535,7 @@ ivas_error ivas_init_encoder( } } - for ( sce_id = 0; sce_id < st_ivas->nSCE; sce_id++ ) + for ( sce_id = 0; sce_id < st_ivas->nSCE; sce_id++ ) // VE: TBV - is this loop needed? { if ( ( error = create_sce_enc( st_ivas, sce_id, ivas_total_brate / st_ivas->nchan_transport ) ) != IVAS_ERR_OK ) { @@ -540,21 +573,92 @@ ivas_error ivas_init_encoder( } } } +#ifdef MASA_AND_OBJECTS + else if ( ivas_format == MASA_ISM_FORMAT ) + { + int32_t element_brate_tmp[MAX_NUM_OBJECTS]; + int32_t ism_total_brate; + int16_t k; + + st_ivas->ism_mode = ivas_omasa_ism_mode_select( ivas_total_brate, hEncoderConfig->nchan_ism ); + st_ivas->nchan_transport = 2; + + if ( ( error = ivas_ism_metadata_enc_create( st_ivas, hEncoderConfig->nchan_ism, element_brate_tmp ) ) != IVAS_ERR_OK ) + { + return error; + } + + k = 0; + while ( k < SIZE_IVAS_BRATE_TBL && ivas_total_brate != ivas_brate_tbl[k] ) + { + k++; + } + + ism_total_brate = 0; + for ( sce_id = 0; sce_id < st_ivas->nSCE; sce_id++ ) + { + ism_total_brate += sep_object_brate[k - 2][st_ivas->nSCE - 1]; + if ( ( error = create_sce_enc( st_ivas, sce_id, sep_object_brate[k - 2][st_ivas->nSCE - 1] ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + if ( ( error = ivas_qmetadata_open( &( st_ivas->hQMetaData ) ) ) != IVAS_ERR_OK ) + { + return error; + } + + for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ ) + { + set_f( st_ivas->hQMetaData->masa_to_total_energy_ratio[i], 0, MASA_FREQUENCY_BANDS ); + } + + if ( ( error = ivas_masa_enc_open( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( st_ivas->ism_mode != ISM_MASA_MODE_DISC ) + { + if ( ( error = ivas_omasa_enc_open( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + if ( ivas_total_brate - ism_total_brate >= MIN_BRATE_MDCT_STEREO ) + { + st_ivas->hEncoderConfig->element_mode_init = IVAS_CPE_MDCT; + } + else + { + st_ivas->hEncoderConfig->element_mode_init = IVAS_CPE_DFT; + } + + if ( ( error = create_cpe_enc( st_ivas, 0, ivas_total_brate - ism_total_brate ) ) != IVAS_ERR_OK ) + { + return error; + } + } +#endif else if ( ivas_format == MC_FORMAT ) { st_ivas->mc_mode = ivas_mc_mode_select( hEncoderConfig->mc_input_setup, ivas_total_brate ); hEncoderConfig->nchan_inp = ivas_mc_ls_setup_get_num_channels( hEncoderConfig->mc_input_setup ); +#ifdef FIX_572_LFE_LPF_ENC if ( ( error = ivas_create_lfe_lpf_enc( &st_ivas->hLfeLpf, hEncoderConfig->input_Fs ) ) != IVAS_ERR_OK ) { return error; } +#endif if ( st_ivas->mc_mode == MC_MODE_MCT ) { st_ivas->nSCE = 0; - st_ivas->nCPE = hEncoderConfig->nchan_inp / 2; + st_ivas->nCPE = hEncoderConfig->nchan_inp / CPE_CHANNELS; for ( cpe_id = 0; cpe_id < st_ivas->nCPE; cpe_id++ ) { @@ -612,7 +716,7 @@ ivas_error ivas_init_encoder( return error; } - for ( cpe_id = 0; cpe_id < st_ivas->nCPE; cpe_id++ ) + for ( cpe_id = 0; cpe_id < st_ivas->nCPE; cpe_id++ ) // VE: TBV - is this loop needed? { if ( ( error = create_cpe_enc( st_ivas, cpe_id, ivas_total_brate / ( st_ivas->nCPE + st_ivas->nSCE ) ) ) != IVAS_ERR_OK ) { @@ -651,7 +755,7 @@ ivas_error ivas_init_encoder( ivas_mcmasa_split_brate( st_ivas->hMcMasa->separateChannelEnabled, ivas_total_brate, st_ivas->nSCE, st_ivas->nCPE, &brate_sce, &brate_cpe ); - for ( sce_id = 0; sce_id < st_ivas->nSCE; sce_id++ ) + for ( sce_id = 0; sce_id < st_ivas->nSCE; sce_id++ ) // VE: TBV - is this loop needed? { if ( ( error = create_sce_enc( st_ivas, sce_id, brate_sce ) ) != IVAS_ERR_OK ) { @@ -659,7 +763,7 @@ ivas_error ivas_init_encoder( } } - for ( cpe_id = 0; cpe_id < st_ivas->nCPE; cpe_id++ ) + for ( cpe_id = 0; cpe_id < st_ivas->nCPE; cpe_id++ ) // VE: TBV - is this loop needed? { hEncoderConfig->element_mode_init = IVAS_CPE_MDCT; @@ -918,7 +1022,11 @@ void ivas_destroy_enc( } /* ISM metadata handles */ +#ifdef MASA_AND_OBJECTS + ivas_ism_metadata_close( st_ivas->hIsmMetaData, 0 ); +#else ivas_ism_metadata_close( st_ivas->hIsmMetaData ); +#endif /* ISM DTX Handle */ if ( st_ivas->hISMDTX != NULL ) @@ -952,8 +1060,10 @@ void ivas_destroy_enc( /* LFE handle */ ivas_lfe_enc_close( &( st_ivas->hLFE ) ); +#ifdef FIX_572_LFE_LPF_ENC /* LFE low pass filter state */ ivas_lfe_lpf_enc_close( &( st_ivas->hLfeLpf ) ); +#endif /* Param-Upmix MC handle */ ivas_mc_paramupmix_enc_close( &( st_ivas->hMCParamUpmix ), st_ivas->hEncoderConfig->input_Fs ); @@ -964,6 +1074,11 @@ void ivas_destroy_enc( /* Multi-channel MASA handle */ ivas_mcmasa_enc_close( &( st_ivas->hMcMasa ), st_ivas->hEncoderConfig->input_Fs ); +#ifdef MASA_AND_OBJECTS + /* OMASA handle */ + ivas_omasa_enc_close( &( st_ivas->hOMasa ) ); +#endif + /* Stereo downmix for EVS encoder handle */ stereo_dmx_evs_close_encoder( &( st_ivas->hStereoDmxEVS ) ); diff --git a/lib_enc/ivas_ism_enc.c b/lib_enc/ivas_ism_enc.c index 558455f017ce43db2b4cdf4cf1bdfadd0c87bf86..472ff1a6424e4cc47cd8d42752ff366031bc8381 100644 --- a/lib_enc/ivas_ism_enc.c +++ b/lib_enc/ivas_ism_enc.c @@ -53,6 +53,10 @@ ivas_error ivas_ism_enc( float data[MAX_NUM_OBJECTS][L_FRAME48k], /* i : input signal */ const int16_t input_frame, /* i : input frame length per channel */ int16_t *nb_bits_metadata /* i : number of metadata bits */ +#ifdef MASA_AND_OBJECTS + , + const int16_t flag_omasa_ener_brate /* i : less bitrate for objects in OMASA flag */ +#endif ) { SCE_ENC_HANDLE hSCE; @@ -88,6 +92,10 @@ ivas_error ivas_ism_enc( int16_t nchan_ism, dtx_flag, sid_flag, flag_noisy_speech; int16_t md_diff_flag[MAX_NUM_OBJECTS]; Encoder_State *prev_st = NULL; +#ifdef MASA_AND_OBJECTS + int32_t ism_total_brate_ref, ism_total_brate; + int16_t i, nchan_transport_ism; +#endif ivas_error error; push_wmops( "ivas_ism_enc" ); @@ -105,12 +113,29 @@ ivas_error ivas_ism_enc( nchan_ism = st_ivas->hEncoderConfig->nchan_ism; set_s( md_diff_flag, 1, nchan_ism ); +#ifdef MASA_AND_OBJECTS + nchan_transport_ism = st_ivas->nchan_transport; + if ( st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) + { + nchan_transport_ism = 1; + nchan_ism = 1; + } + else if ( st_ivas->ism_mode == ISM_MASA_MODE_DISC ) + { + nchan_transport_ism = st_ivas->hEncoderConfig->nchan_ism; + } +#endif + /*------------------------------------------------------------------* * Preprocesing *-----------------------------------------------------------------*/ +#ifdef MASA_AND_OBJECTS + for ( sce_id = 0; sce_id < nchan_transport_ism; sce_id++ ) +#else /* in ISM format: st_ivas->nchan_transport = st_ivas->nSCE */ for ( sce_id = 0; sce_id < st_ivas->nchan_transport; sce_id++ ) +#endif { hSCE = st_ivas->hSCE[sce_id]; st = hSCE->hCoreCoder[0]; @@ -222,11 +247,41 @@ ivas_error ivas_ism_enc( } else if ( st_ivas->ism_mode == ISM_MODE_PARAM ) { +#ifdef MASA_AND_OBJECTS + ivas_ism_metadata_enc( &st_ivas->hEncoderConfig->ivas_total_brate, nchan_ism, nchan_transport_ism, st_ivas->hIsmMetaData, st_ivas->hSCE, st_ivas->hSCE[st_ivas->nSCE - 1]->hMetaData, + nb_bits_metadata, vad_flag, st_ivas->ism_mode, st_ivas->hDirAC->hParamIsm, st_ivas->hEncoderConfig->ism_extended_metadata_flag, -1, 0, NULL ); +#else ivas_ism_metadata_enc( st_ivas->hEncoderConfig->ivas_total_brate, nchan_ism, st_ivas->nchan_transport, st_ivas->hIsmMetaData, st_ivas->hSCE, st_ivas->hSCE[st_ivas->nSCE - 1]->hMetaData, nb_bits_metadata, vad_flag, st_ivas->ism_mode, st_ivas->hDirAC->hParamIsm, st_ivas->hEncoderConfig->ism_extended_metadata_flag ); +#endif } else /* ISM_MODE_DISC */ { +#ifdef MASA_AND_OBJECTS + if ( st_ivas->ism_mode == ISM_MASA_MODE_DISC || st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) + { + ism_total_brate = 0; + for ( i = 0; i < st_ivas->nSCE; i++ ) + { + ism_total_brate += st_ivas->hSCE[i]->element_brate; + } + } + else + { + ism_total_brate = st_ivas->hEncoderConfig->ivas_total_brate; + } + + ism_total_brate_ref = ism_total_brate; + + ivas_ism_metadata_enc( &ism_total_brate, nchan_ism, nchan_transport_ism, st_ivas->hIsmMetaData, st_ivas->hSCE, st_ivas->hSCE[st_ivas->nSCE - 1]->hMetaData, + nb_bits_metadata, vad_flag, st_ivas->ism_mode, NULL, st_ivas->hEncoderConfig->ism_extended_metadata_flag, st_ivas->hMasa != NULL ? st_ivas->hMasa->data.lp_noise_CPE : 0, flag_omasa_ener_brate, st_ivas->hMasa != NULL ? &( st_ivas->hMasa->data.omasa_stereo_sw_cnt ) : NULL ); + + if ( st_ivas->hEncoderConfig->ivas_format == MASA_ISM_FORMAT ) + { + st_ivas->hCPE[0]->brate_surplus = ism_total_brate_ref - ism_total_brate; + } +#else ivas_ism_metadata_enc( st_ivas->hEncoderConfig->ivas_total_brate, nchan_ism, st_ivas->nchan_transport, st_ivas->hIsmMetaData, st_ivas->hSCE, st_ivas->hSCE[st_ivas->nSCE - 1]->hMetaData, nb_bits_metadata, vad_flag, st_ivas->ism_mode, NULL, st_ivas->hEncoderConfig->ism_extended_metadata_flag ); +#endif } update_last_metadata( nchan_ism, st_ivas->hIsmMetaData, md_diff_flag ); @@ -246,7 +301,11 @@ ivas_error ivas_ism_enc( * CoreCoders encoding *-----------------------------------------------------------------*/ +#ifdef MASA_AND_OBJECTS + for ( sce_id = 0; sce_id < nchan_transport_ism; sce_id++ ) +#else for ( sce_id = 0; sce_id < st_ivas->nchan_transport; sce_id++ ) +#endif { hSCE = st_ivas->hSCE[sce_id]; st = hSCE->hCoreCoder[0]; @@ -310,7 +369,11 @@ ivas_error ivas_ism_enc( if ( dtx_flag ) { +#ifdef MASA_AND_OBJECTS + for ( sce_id = 0; sce_id < nchan_transport_ism; sce_id++ ) +#else for ( sce_id = 0; sce_id < st_ivas->nchan_transport; sce_id++ ) +#endif { if ( sce_id != st_ivas->hISMDTX->sce_id_dtx ) { @@ -328,7 +391,11 @@ ivas_error ivas_ism_enc( int16_t id, n; n = 0; +#ifdef MASA_AND_OBJECTS + for ( sce_id = 0; sce_id < nchan_transport_ism; sce_id++ ) +#else for ( sce_id = 0; sce_id < st_ivas->nchan_transport; sce_id++ ) +#endif { if ( sce_id != st_ivas->hISMDTX->sce_id_dtx ) { @@ -405,7 +472,12 @@ ivas_error ivas_ism_enc_config( st_ivas->nSCE = st_ivas->nchan_transport; st_ivas->nCPE = 0; - if ( ( error = ivas_ism_config( st_ivas->hEncoderConfig->ivas_total_brate, st_ivas->nchan_transport, st_ivas->hEncoderConfig->nchan_inp, NULL, 0, NULL, NULL, element_brate_tmp, NULL, NULL ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_ism_config( st_ivas->hEncoderConfig->ivas_total_brate, st_ivas->nchan_transport, st_ivas->hEncoderConfig->nchan_inp, NULL, 0, NULL, NULL, element_brate_tmp, NULL, NULL +#ifdef MASA_AND_OBJECTS + , + 0 +#endif + ) ) != IVAS_ERR_OK ) { return error; } diff --git a/lib_enc/ivas_ism_metadata_enc.c b/lib_enc/ivas_ism_metadata_enc.c index ed43af153d0c8fc3294b60e8d156165ebb6c9c9c..0b8133ac34b42735b3919991afdfa77905a9d17e 100644 --- a/lib_enc/ivas_ism_metadata_enc.c +++ b/lib_enc/ivas_ism_metadata_enc.c @@ -168,7 +168,11 @@ static void rate_ism_importance( *-------------------------------------------------------------------------*/ ivas_error ivas_ism_metadata_enc( - const int32_t ism_total_brate, /* i : ISM total bitrate */ +#ifdef MASA_AND_OBJECTS + int32_t *ism_total_brate, /* i/o: ISM total bitrate */ +#else + const int32_t ism_total_brate, /* i : ISM total bitrate */ +#endif const int16_t nchan_ism, /* i : number of ISM channels */ const int16_t nchan_transport, /* i : number of transport channels */ ISM_METADATA_HANDLE hIsmMeta[], /* i/o: ISM metadata handles */ @@ -179,6 +183,12 @@ ivas_error ivas_ism_metadata_enc( const int16_t ism_mode, /* i : ISM mode */ const PARAM_ISM_CONFIG_HANDLE hParamIsm, /* i : Param ISM Enc Handle */ const int16_t ism_extended_metadata_flag /* i : Extended metadata flag */ +#ifdef MASA_AND_OBJECTS + , + const float lp_noise_CPE, + const int16_t flag_omasa_ener_brate, /* i : less bitrate for objects in OMASA flag */ + int16_t *omasa_stereo_sw_cnt +#endif ) { int16_t i, ch, nb_bits_start = 0; @@ -216,73 +226,104 @@ ivas_error ivas_ism_metadata_enc( set_s( null_metadata_flag, 0, nchan_ism ); set_s( lowrate_metadata_flag, 0, nchan_ism ); - /*----------------------------------------------------------------* - * Set Metadata presence / importance flag - *----------------------------------------------------------------*/ +#ifdef MASA_AND_OBJECTS + if ( ism_mode == ISM_MASA_MODE_DISC || ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) + { + /*----------------------------------------------------------------* + * Rate importance of particular ISM streams in combined format coding + *----------------------------------------------------------------*/ - for ( ch = 0; ch < nchan_ism; ch++ ) + set_ism_importance_interformat( *ism_total_brate, nchan_transport, hIsmMeta, hSCE, lp_noise_CPE, ism_imp ); + } + else { - if ( ism_mode == ISM_MODE_PARAM ) +#endif + /*----------------------------------------------------------------* + * Set Metadata presence / importance flag + *----------------------------------------------------------------*/ + + for ( ch = 0; ch < nchan_ism; ch++ ) { - hIsmMeta[ch]->ism_metadata_flag = 1; - } + if ( ism_mode == ISM_MODE_PARAM ) + { + hIsmMeta[ch]->ism_metadata_flag = 1; + } +#ifdef MASA_AND_OBJECTS + else if ( ism_mode == ISM_MODE_DISC || ism_mode == ISM_MASA_MODE_DISC ) +#else else if ( ism_mode == ISM_MODE_DISC ) - { - null_metadata_flag[ch] = !hIsmMeta[ch]->ism_metadata_flag; - - if ( hIsmMeta[ch]->ism_metadata_flag == 1 ) +#endif { - /* In case of low level noise for low bitrate inactive frames, do not sent metadata */ - hIsmMeta[ch]->ism_metadata_flag = vad_flag[ch] || hSCE[ch]->hCoreCoder[0]->lp_noise > 10 || hSCE[ch]->hCoreCoder[0]->tcxonly; + null_metadata_flag[ch] = !hIsmMeta[ch]->ism_metadata_flag; - /* in inactive frames, send MD 1) in ISM_MD_INC_DIFF_CNT_MAX consecutive frames when MD significantly change, 2) at least every ISM_MD_FEC_DIFF frames */ - if ( hIsmMeta[ch]->ism_metadata_flag == 0 ) + if ( hIsmMeta[ch]->ism_metadata_flag == 1 ) { - if ( ( fabsf( hIsmMeta[ch]->azimuth - hIsmMeta[ch]->last_true_azimuth ) > ISM_MD_FEC_DIFF ) || - ( fabsf( hIsmMeta[ch]->elevation - hIsmMeta[ch]->last_true_elevation ) > ISM_MD_FEC_DIFF ) || ( fabsf( hIsmMeta[ch]->radius - hIsmMeta[ch]->last_true_radius ) > ISM_MD_RAD_FEC_DIFF ) ) - { - lowrate_metadata_flag[ch] = 1; - hIsmMeta[ch]->ism_md_inc_diff_cnt = 0; - } - else if ( hIsmMeta[ch]->ism_md_inc_diff_cnt < ISM_MD_INC_DIFF_CNT_MAX ) + /* In case of low level noise for low bitrate inactive frames, do not sent metadata */ + hIsmMeta[ch]->ism_metadata_flag = vad_flag[ch] || hSCE[ch]->hCoreCoder[0]->lp_noise > 10 || hSCE[ch]->hCoreCoder[0]->tcxonly; + + /* in inactive frames, send MD 1) in ISM_MD_INC_DIFF_CNT_MAX consecutive frames when MD significantly change, 2) at least every ISM_MD_FEC_DIFF frames */ + if ( hIsmMeta[ch]->ism_metadata_flag == 0 ) { - lowrate_metadata_flag[ch] = 1; + if ( ( fabsf( hIsmMeta[ch]->azimuth - hIsmMeta[ch]->last_true_azimuth ) > ISM_MD_FEC_DIFF ) || + ( fabsf( hIsmMeta[ch]->elevation - hIsmMeta[ch]->last_true_elevation ) > ISM_MD_FEC_DIFF ) || ( fabsf( hIsmMeta[ch]->radius - hIsmMeta[ch]->last_true_radius ) > ISM_MD_RAD_FEC_DIFF ) ) + { + + lowrate_metadata_flag[ch] = 1; - if ( hIsmMeta[ch]->ism_md_inc_diff_cnt % 2 == 0 ) + hIsmMeta[ch]->ism_md_inc_diff_cnt = 0; + } + else if ( hIsmMeta[ch]->ism_md_inc_diff_cnt < ISM_MD_INC_DIFF_CNT_MAX ) { - hIsmMeta[ch]->position_angle.angle1_diff_cnt = ISM_FEC_MAX; + + lowrate_metadata_flag[ch] = 1; + + if ( hIsmMeta[ch]->ism_md_inc_diff_cnt % 2 == 0 ) + { + hIsmMeta[ch]->position_angle.angle1_diff_cnt = ISM_FEC_MAX; + } + else + { + hIsmMeta[ch]->position_angle.angle2_diff_cnt = ISM_FEC_MAX; + } } - else + else if ( hIsmMeta[ch]->ism_md_fec_cnt_enc == ISM_MD_FEC_CNT_MAX ) { - hIsmMeta[ch]->position_angle.angle2_diff_cnt = ISM_FEC_MAX; + + lowrate_metadata_flag[ch] = 1; + + hIsmMeta[ch]->position_angle.angle1_diff_cnt = ISM_FEC_MAX; } } - else if ( hIsmMeta[ch]->ism_md_fec_cnt_enc == ISM_MD_FEC_CNT_MAX ) - { - lowrate_metadata_flag[ch] = 1; - hIsmMeta[ch]->position_angle.angle1_diff_cnt = ISM_FEC_MAX; - } } } } - } - /*----------------------------------------------------------------* - * Rate importance of particular ISM streams - *----------------------------------------------------------------*/ + /*----------------------------------------------------------------* + * Rate importance of particular ISM streams + *----------------------------------------------------------------*/ - rate_ism_importance( nchan_transport, hIsmMeta, hSCE, lowrate_metadata_flag, ism_imp ); + rate_ism_importance( nchan_transport, hIsmMeta, hSCE, lowrate_metadata_flag, ism_imp ); +#ifdef MASA_AND_OBJECTS + } +#endif /*----------------------------------------------------------------* * Write ISM common signaling *----------------------------------------------------------------*/ - /* write number of objects - unary coding */ - for ( ch = 1; ch < nchan_ism; ch++ ) +#ifdef MASA_AND_OBJECTS + if ( ism_mode != ISM_MASA_MODE_DISC && ism_mode != ISM_MASA_MODE_MASA_ONE_OBJ ) { - push_indice( hBstr, IND_ISM_NUM_OBJECTS, 1, 1 ); +#endif + /* write number of objects - unary coding */ + for ( ch = 1; ch < nchan_ism; ch++ ) + { + push_indice( hBstr, IND_ISM_NUM_OBJECTS, 1, 1 ); + } + push_indice( hBstr, IND_ISM_NUM_OBJECTS, 0, 1 ); +#ifdef MASA_AND_OBJECTS } - push_indice( hBstr, IND_ISM_NUM_OBJECTS, 0, 1 ); +#endif for ( ch = 0; ch < nchan_ism; ch++ ) { @@ -292,7 +333,11 @@ ivas_error ivas_ism_metadata_enc( } /* write extended metadata presence flag */ +#ifdef MASA_AND_OBJECTS + if ( ism_mode == ISM_MODE_DISC && *ism_total_brate >= ISM_EXTENDED_METADATA_BRATE ) +#else if ( ism_total_brate >= ISM_EXTENDED_METADATA_BRATE ) +#endif { push_indice( hBstr, IND_ISM_EXTENDED_FLAG, ism_extended_metadata_flag, ISM_EXTENDED_METADATA_BITS ); @@ -306,28 +351,42 @@ ivas_error ivas_ism_metadata_enc( /* write ISM metadata flag (one per object) */ for ( ch = 0; ch < nchan_transport; ch++ ) { - if ( null_metadata_flag[ch] ) +#ifdef MASA_AND_OBJECTS + if ( ism_mode == ISM_MASA_MODE_DISC || ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) { - /* signal NULL metadata frame */ - push_indice( hBstr, IND_ISM_MD_NULL_FLAG, 1, ISM_METADATA_MD_FLAG_BITS ); - - /* write the ISM class to ISM_NO_META and again the true ISM class */ - push_indice( hBstr, IND_ISM_METADATA_FLAG, ISM_NO_META, ISM_METADATA_FLAG_BITS ); - push_indice( hBstr, IND_ISM_MD_INACTIVE_FLAG, ism_imp[ch], ISM_METADATA_FLAG_BITS ); + /* flags will be written in ivas_masa_encode() */ + hIsmMeta[ch]->ism_imp = ism_imp[ch]; + hIsmMeta[ch]->ism_md_null_flag = null_metadata_flag[ch]; + hIsmMeta[ch]->ism_md_lowrate_flag = lowrate_metadata_flag[ch]; } else { - push_indice( hBstr, IND_ISM_METADATA_FLAG, ism_imp[ch], ISM_METADATA_FLAG_BITS ); +#endif + if ( null_metadata_flag[ch] ) + { + /* signal NULL metadata frame */ + push_indice( hBstr, IND_ISM_MD_NULL_FLAG, 1, ISM_METADATA_MD_FLAG_BITS ); - if ( ism_imp[ch] == ISM_NO_META ) + /* write the ISM class to ISM_NO_META and again the true ISM class */ + push_indice( hBstr, IND_ISM_METADATA_FLAG, ISM_NO_META, ISM_METADATA_FLAG_BITS ); + push_indice( hBstr, IND_ISM_MD_INACTIVE_FLAG, ism_imp[ch], ISM_METADATA_FLAG_BITS ); + } + else { - /* signal low-rate ISM_NO_META frame */ - push_indice( hBstr, IND_ISM_MD_NULL_FLAG, 0, ISM_METADATA_MD_FLAG_BITS ); + push_indice( hBstr, IND_ISM_METADATA_FLAG, ism_imp[ch], ISM_METADATA_FLAG_BITS ); - /* signal presence of MD in low-rate ISM_NO_META frame */ - push_indice( hBstr, IND_ISM_MD_INACTIVE_FLAG, lowrate_metadata_flag[ch], ISM_METADATA_INACTIVE_FLAG_BITS ); + if ( ism_imp[ch] == ISM_NO_META ) + { + /* signal low-rate ISM_NO_META frame */ + push_indice( hBstr, IND_ISM_MD_NULL_FLAG, 0, ISM_METADATA_MD_FLAG_BITS ); + + /* signal presence of MD in low-rate ISM_NO_META frame */ + push_indice( hBstr, IND_ISM_MD_INACTIVE_FLAG, lowrate_metadata_flag[ch], ISM_METADATA_INACTIVE_FLAG_BITS ); + } } +#ifdef MASA_AND_OBJECTS } +#endif } @@ -349,13 +408,18 @@ ivas_error ivas_ism_metadata_enc( for ( ch = 0; ch < nchan_ism; ch++ ) { hIsmMetaData = hIsmMeta[ch]; +#ifdef MASA_AND_OBJECTS + if ( ism_mode == ISM_MODE_DISC || ism_mode == ISM_MASA_MODE_DISC || ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) +#else if ( ism_mode == ISM_MODE_DISC ) +#endif { nb_bits_start = hBstr->nb_bits_tot; } if ( hIsmMeta[ch]->ism_metadata_flag || lowrate_metadata_flag[ch] ) { + /*----------------------------------------------------------------* * Quantize and encode azimuth and elevation *----------------------------------------------------------------*/ @@ -384,7 +448,11 @@ ivas_error ivas_ism_metadata_enc( } else { +#ifdef MASA_AND_OBJECTS + if ( ism_mode == ISM_MODE_DISC || ism_mode == ISM_MASA_MODE_DISC || ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) +#else if ( ism_mode == ISM_MODE_DISC ) +#endif { idx_angle1_abs = ism_quant_meta( hIsmMetaData->azimuth, &valQ, ism_azimuth_borders, ISM_Q_STEP, ISM_Q_STEP_BORDER, 1 << ISM_AZIMUTH_NBITS ); idx_angle2_abs = ism_quant_meta( hIsmMetaData->elevation, &valQ, ism_elevation_borders, ISM_Q_STEP, ISM_Q_STEP_BORDER, 1 << ISM_ELEVATION_NBITS ); @@ -413,7 +481,11 @@ ivas_error ivas_ism_metadata_enc( } /* save number of metadata bits written */ +#ifdef MASA_AND_OBJECTS + if ( ism_mode == ISM_MODE_DISC || ism_mode == ISM_MASA_MODE_DISC || ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) +#else if ( ism_mode == ISM_MODE_DISC ) +#endif { nb_bits_metadata[ch] = hBstr->nb_bits_tot - nb_bits_start; } @@ -546,14 +618,82 @@ ivas_error ivas_ism_metadata_enc( } } +#ifdef MASA_AND_OBJECTS + /*----------------------------------------------------------------* + * Take into account the combined format bit-budget distribution + *----------------------------------------------------------------*/ + + if ( ism_mode == ISM_MASA_MODE_DISC || ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) + { + int16_t bits_ism, bits_element[MAX_NUM_OBJECTS]; + int16_t brate_limit_flag; + int32_t ism_total_brate_ref; + ism_total_brate_ref = *ism_total_brate; + brate_limit_flag = calculate_brate_limit_flag( ism_imp, nchan_ism ); + + bits_ism = (int16_t) ( *ism_total_brate / FRAMES_PER_SECOND ); + set_s( bits_element, bits_ism / nchan_ism, nchan_ism ); + bits_element[nchan_ism - 1] += bits_ism % nchan_ism; + bitbudget_to_brate( bits_element, element_brate, nchan_ism ); + + *ism_total_brate = 0; + for ( ch = 0; ch < nchan_ism; ch++ ) + { + *ism_total_brate += ivas_interformat_brate( ism_mode, nchan_ism, hSCE[ch]->element_brate, ism_imp[ch], brate_limit_flag ); + + if ( ism_imp[ch] > 1 && flag_omasa_ener_brate == 1 && brate_limit_flag >= 0 ) + { + *ism_total_brate -= ADJUST_ISM_BRATE_NEG; + } + + if ( brate_limit_flag == -1 && ism_imp[ch] >= 1 && nchan_ism >= 3 && ( ism_total_brate_ref - *ism_total_brate > IVAS_48k ) ) + { + *ism_total_brate += ADJUST_ISM_BRATE_POS; + } + } + ism_metadata_flag_global = 1; + + if ( ism_mode == ISM_MASA_MODE_DISC ) + { + brate_limit_flag = 0; + for ( int16_t n = 0; n < nchan_ism; n++ ) + { + brate_limit_flag += ism_imp[n]; + } + + if ( brate_limit_flag >= nchan_ism * ISM_HIGH_IMP - 2 ) + { + *omasa_stereo_sw_cnt = OMASA_STEREO_SW_CNT_MAX; + } + } + } +#endif + /*----------------------------------------------------------------* * Configuration and decision about bitrates per channel *----------------------------------------------------------------*/ +#ifdef MASA_AND_OBJECTS + if ( ism_mode == ISM_MASA_MODE_DISC || ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) + { + if ( ( error = ivas_ism_config( *ism_total_brate, nchan_transport, nchan_ism, hIsmMeta, ism_extended_metadata_flag, null_metadata_flag, ism_imp, element_brate, total_brate, nb_bits_metadata, 1 ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else + { + if ( ( error = ivas_ism_config( *ism_total_brate, nchan_transport, nchan_ism, hIsmMeta, ism_extended_metadata_flag, null_metadata_flag, ism_imp, element_brate, total_brate, nb_bits_metadata, 0 ) ) != IVAS_ERR_OK ) + { + return error; + } + } +#else if ( ( error = ivas_ism_config( ism_total_brate, nchan_transport, nchan_ism, hIsmMeta, ism_extended_metadata_flag, null_metadata_flag, ism_imp, element_brate, total_brate, nb_bits_metadata ) ) != IVAS_ERR_OK ) { return error; } +#endif for ( ch = 0; ch < nchan_ism; ch++ ) { @@ -571,13 +711,47 @@ ivas_error ivas_ism_metadata_enc( hIsmMeta[ch]->ism_md_inc_diff_cnt = min( hIsmMeta[ch]->ism_md_inc_diff_cnt, ISM_MD_INC_DIFF_CNT_MAX ); } +#ifdef MASA_AND_OBJECTS for ( ch = 0; ch < nchan_transport; ch++ ) { hSCE[ch]->hCoreCoder[0]->low_rate_mode = 0; if ( ism_mode == ISM_MODE_DISC ) { +#ifdef FIX_562_ISM2_64KBPS if ( ism_imp[ch] == ISM_NO_META && ( ( total_brate[ch] < ACELP_8k00 && element_brate[ch] < SCE_CORE_16k_LOW_LIMIT ) || ( total_brate[ch] <= ACELP_16k_LOW_LIMIT && element_brate[ch] >= SCE_CORE_16k_LOW_LIMIT ) ) ) +#else + if ( ism_imp[ch] == ISM_NO_META && total_brate[ch] < ACELP_8k00 ) +#endif + { + hSCE[ch]->hCoreCoder[0]->low_rate_mode = 1; + } + + hSCE[ch]->element_brate = element_brate[ch]; + } + else if ( ism_mode == ISM_MASA_MODE_DISC || ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) + { + if ( ism_imp[ch] == ISM_INACTIVE_IMP ) + { + hSCE[ch]->hCoreCoder[0]->low_rate_mode = 1; + } + } + + hSCE[ch]->hCoreCoder[0]->total_brate = total_brate[ch]; + + /* write metadata only in active frames */ + if ( hSCE[0]->hCoreCoder[0]->core_brate > SID_2k40 ) + { + reset_indices_enc( hSCE[ch]->hMetaData, hSCE[ch]->hMetaData->nb_ind_tot ); + } + } +#else + for ( ch = 0; ch < nchan_transport; ch++ ) + { + hSCE[ch]->hCoreCoder[0]->low_rate_mode = 0; + if ( ism_mode == ISM_MODE_DISC ) + { + if ( hIsmMeta[ch]->ism_metadata_flag == 0 && localVAD[ch] == 0 && ism_metadata_flag_global ) { hSCE[ch]->hCoreCoder[0]->low_rate_mode = 1; } @@ -592,6 +766,7 @@ ivas_error ivas_ism_metadata_enc( reset_indices_enc( hSCE[ch]->hMetaData, hSCE[ch]->hMetaData->nb_ind_tot ); } } +#endif pop_wmops(); @@ -614,18 +789,46 @@ ivas_error ivas_ism_metadata_enc_create( int16_t ch, nchan_transport; ivas_error error; - if ( st_ivas->ism_mode == ISM_MODE_PARAM ) +#ifdef MASA_AND_OBJECTS + nchan_transport = st_ivas->nchan_transport; + if ( st_ivas->hEncoderConfig->ivas_format == MASA_ISM_FORMAT ) { nchan_transport = MAX_PARAM_ISM_WAVE; + ivas_set_omasa_TC( st_ivas->ism_mode, n_ISms, &st_ivas->nSCE, &st_ivas->nCPE ); } else { - nchan_transport = n_ISms; - } +#endif + if ( st_ivas->ism_mode == ISM_MODE_NONE ) + { + nchan_transport = st_ivas->nchan_transport; + + if ( nchan_transport == 1 ) + { + st_ivas->nSCE = 1; + st_ivas->nCPE = 0; + } + else + { + st_ivas->nSCE = 0; + st_ivas->nCPE = 1; + } + } + else if ( st_ivas->ism_mode == ISM_MODE_PARAM ) + { + nchan_transport = 2; + } + else + { + nchan_transport = n_ISms; + } - st_ivas->nchan_transport = nchan_transport; - st_ivas->nSCE = nchan_transport; - st_ivas->nCPE = 0; + st_ivas->nchan_transport = nchan_transport; + st_ivas->nSCE = nchan_transport; + st_ivas->nCPE = 0; +#ifdef MASA_AND_OBJECTS + } +#endif /* allocate ISM metadata handles */ for ( ch = 0; ch < n_ISms; ch++ ) @@ -646,6 +849,14 @@ ivas_error ivas_ism_metadata_enc_create( st_ivas->hIsmMetaData[ch]->radius_diff_cnt = ISM_FEC_MAX - 2; st_ivas->hIsmMetaData[ch]->last_ism_metadata_flag = 0; +#ifdef MASA_AND_OBJECTS + st_ivas->hIsmMetaData[ch]->ism_imp = -1; + st_ivas->hIsmMetaData[ch]->ism_md_null_flag = 0; + st_ivas->hIsmMetaData[ch]->ism_md_lowrate_flag = 0; + st_ivas->hIsmMetaData[ch]->q_azimuth_old = 0.0f; + st_ivas->hIsmMetaData[ch]->q_elevation_old = 0.0f; +#endif + ivas_ism_reset_metadata( st_ivas->hIsmMetaData[ch] ); st_ivas->hIsmMetaData[ch]->last_azimuth = 0.0f; @@ -658,10 +869,37 @@ ivas_error ivas_ism_metadata_enc_create( st_ivas->hIsmMetaData[ch]->last_true_radius = 1.0f; } +#ifdef MASA_AND_OBJECTS + if ( st_ivas->hEncoderConfig->ivas_format == MASA_ISM_FORMAT ) + { + if ( st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) + { + if ( ( error = ivas_ism_config( st_ivas->hEncoderConfig->ivas_total_brate, nchan_transport, 1, NULL, 0, NULL, NULL, element_brate_tmp, NULL, NULL, 1 ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else if ( st_ivas->ism_mode == ISM_MASA_MODE_DISC ) + { + if ( ( error = ivas_ism_config( st_ivas->hEncoderConfig->ivas_total_brate, nchan_transport, n_ISms, NULL, 0, NULL, NULL, element_brate_tmp, NULL, NULL, 1 ) ) != IVAS_ERR_OK ) + { + return error; + } + } + } + else + { + if ( ( error = ivas_ism_config( st_ivas->hEncoderConfig->ivas_total_brate, nchan_transport, n_ISms, NULL, 0, NULL, NULL, element_brate_tmp, NULL, NULL, 0 ) ) != IVAS_ERR_OK ) + { + return error; + } + } +#else if ( ( error = ivas_ism_config( st_ivas->hEncoderConfig->ivas_total_brate, nchan_transport, n_ISms, NULL, 0, NULL, NULL, element_brate_tmp, NULL, NULL ) ) != IVAS_ERR_OK ) { return error; } +#endif return IVAS_ERR_OK; } diff --git a/lib_enc/ivas_ism_param_enc.c b/lib_enc/ivas_ism_param_enc.c index 7c99c491844d1622f27d41f07c057abe9167bfa8..c3d50d24db4d73de5ceceb14aef7fda314b246e1 100644 --- a/lib_enc/ivas_ism_param_enc.c +++ b/lib_enc/ivas_ism_param_enc.c @@ -222,9 +222,11 @@ void ivas_param_ism_stereo_dmx( float alpha, azi_shift, tmp, tmp_1; float cardioid_left[MAX_NUM_OBJECTS], cardioid_right[MAX_NUM_OBJECTS]; float stereo_dmx[2][L_FRAME48k]; +#ifdef FIX_549_DMX_GAIN float dmx_gain, ene_dmx, ene_data, grad; float last_dmx_gain; float last_cardioid_left; +#endif ISM_METADATA_HANDLE hIsmMetaData; push_wmops( "ivas_param_ism_st_dmx" ); @@ -232,10 +234,12 @@ void ivas_param_ism_stereo_dmx( /*Initialization*/ alpha = 0.5; azi_shift = 0; +#ifdef FIX_549_DMX_GAIN dmx_gain = 0; ene_dmx = 0; ene_data = 0; last_dmx_gain = st_ivas->hDirAC->hParamIsm->last_dmx_gain; +#endif /* Set the stereo dmx to zero */ set_zero( stereo_dmx[0], L_FRAME48k ); @@ -245,11 +249,24 @@ void ivas_param_ism_stereo_dmx( for ( i = 0; i < st_ivas->hEncoderConfig->nchan_ism; i++ ) { hIsmMetaData = st_ivas->hIsmMetaData[i]; +#ifdef FIX_549_DMX_GAIN last_cardioid_left = st_ivas->hDirAC->hParamIsm->last_cardioid_left[i]; +#endif /*Compute the Cardioids for the corresponding object direction */ tmp = hIsmMetaData->azimuth * ( EVS_PI / 180 ); tmp_1 = ( EVS_PI / 2 ) + azi_shift; cardioid_left[i] = alpha + ( 1 - alpha ) * cosf( tmp - tmp_1 ); +#ifndef FIX_549_DMX_GAIN + cardioid_right[i] = alpha + ( 1 - alpha ) * cosf( tmp + tmp_1 ); + + /* Loop over all samples */ + for ( j = 0; j < input_frame; j++ ) + { + tmp = data[i][j]; + stereo_dmx[0][j] += cardioid_left[i] * tmp; /* DMX Left */ + stereo_dmx[1][j] += cardioid_right[i] * tmp; /* DMX Right */ + } +#else if ( st_ivas->hSCE[0]->hCoreCoder[0]->ini_frame > 0 ) { float last_cardioid_right; @@ -289,8 +306,10 @@ void ivas_param_ism_stereo_dmx( } } st_ivas->hDirAC->hParamIsm->last_cardioid_left[i] = cardioid_left[i]; +#endif } +#ifdef FIX_549_DMX_GAIN /* Energy compensation */ for ( j = 0; j < input_frame; j++ ) { @@ -323,6 +342,7 @@ void ivas_param_ism_stereo_dmx( } } st_ivas->hDirAC->hParamIsm->last_dmx_gain = dmx_gain; +#endif /* Copy the stereo dmx to data variable */ mvr2r( stereo_dmx[0], data[0], input_frame ); mvr2r( stereo_dmx[1], data[1], input_frame ); diff --git a/lib_enc/ivas_lfe_enc.c b/lib_enc/ivas_lfe_enc.c index 75952fe62c5ea06d896707ac409689035d724909..61072cc1872212f424a15b3c834be118c48b8bb9 100644 --- a/lib_enc/ivas_lfe_enc.c +++ b/lib_enc/ivas_lfe_enc.c @@ -344,6 +344,10 @@ void ivas_lfe_enc( zero_pad_len = hLFE->pWindow_state->zero_pad_len; pWindow_coeffs = hLFE->pWindow_state->pWindow_coeffs; +#ifndef FIX_572_LFE_LPF_ENC + /*Low Pass Filter */ + ivas_filter_process( &hLFE->filter_state, data_lfe_ch, input_frame ); +#endif /* Windowing */ ivas_dct_windowing( fade_len, full_len, dct_len, zero_pad_len, pWindow_coeffs, input_frame, wtda_audio, hLFE->old_wtda_audio, data_lfe_ch ); @@ -378,6 +382,9 @@ ivas_error ivas_create_lfe_enc( { int16_t input_frame; LFE_ENC_HANDLE hLFE; +#ifndef FIX_572_LFE_LPF_ENC + const float *filt_coeff; +#endif int16_t i, j; input_frame = (int16_t) ( input_Fs / FRAMES_PER_SEC ); @@ -419,6 +426,10 @@ ivas_error ivas_create_lfe_enc( lfe_window_init( hLFE->pWindow_state, input_Fs, input_frame ); +#ifndef FIX_572_LFE_LPF_ENC + ivas_lfe_lpf_select_filt_coeff( input_Fs, IVAS_FILTER_ORDER_4, &filt_coeff ); + ivas_filters_init( &hLFE->filter_state, filt_coeff, IVAS_FILTER_ORDER_4 ); +#endif /* Initialization for entropy coding */ hLFE->cum_freq_models[0][0] = ivas_str_lfe_freq_models.entropy_coder_model_fine_sg1; @@ -478,6 +489,7 @@ void ivas_lfe_enc_close( return; } +#ifdef FIX_572_LFE_LPF_ENC /*------------------------------------------------------------------------- * ivas_create_lfe_lpf_enc() * @@ -551,3 +563,4 @@ void ivas_lfe_lpf_enc_apply( return; } +#endif diff --git a/lib_enc/ivas_masa_enc.c b/lib_enc/ivas_masa_enc.c index ec8c22bcd9d52bc3ce6047bcd9014350e329e51c..abe899a7945d51bf42e985ce441a678aef6435f3 100644 --- a/lib_enc/ivas_masa_enc.c +++ b/lib_enc/ivas_masa_enc.c @@ -47,8 +47,9 @@ static void combine_freqbands_and_subframes( MASA_ENCODER_HANDLE hMasa ); +#ifndef MASA_AND_OBJECTS static void combine_directions( MASA_ENCODER_HANDLE hMasa ); - +#endif static void find_n_largest( const float *input, int16_t *largestIndices, const int16_t numElements, const int16_t numLargest ); static void move_metadata_to_qmetadata( const MASA_ENCODER_HANDLE hMasa, IVAS_QMETADATA_HANDLE hQMeta ); @@ -59,7 +60,13 @@ static void compensate_energy_ratios( MASA_ENCODER_HANDLE hMasa ); static int16_t encode_lfe_to_total_energy_ratio( MASA_ENCODER_HANDLE hMasa, BSTR_ENC_HANDLE hMetaData, const int32_t ivas_total_brate ); +#ifdef MASA_AND_OBJECTS +static void ivas_encode_masaism_metadata( MASA_ENCODER_HANDLE hMasa, IVAS_QMETADATA_HANDLE hQMetaData, BSTR_ENC_HANDLE hMetaData, ISM_METADATA_HANDLE hIsmMeta[], const int16_t low_bitrate_mode, const int16_t omasa_nbands, const int16_t omasa_nblocks, const int16_t idx_separated_object, const int16_t ism_imp ); + static void reduce_metadata_further( MASA_ENCODER_HANDLE hMasa, IVAS_QMETADATA_HANDLE hqmetadata, const IVAS_FORMAT ivas_format ); +#else +static void reduce_metadata_further( MASA_ENCODER_HANDLE hMasa, IVAS_QMETADATA_HANDLE hqmetadata, const IVAS_FORMAT ivas_format ); +#endif static void average_masa_metadata( MASA_METADATA_FRAME *masaMetadata, float energy[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], const SPHERICAL_GRID_DATA *sphGrid, const uint8_t useSphGrid ); @@ -98,6 +105,9 @@ ivas_error ivas_masa_enc_open( MASA_ENCODER_HANDLE hMasa; ENCODER_CONFIG_HANDLE hEncoderConfig; ivas_error error; +#ifdef MASA_AND_OBJECTS + int32_t ism_total_brate; +#endif error = IVAS_ERR_OK; @@ -107,9 +117,14 @@ ivas_error ivas_masa_enc_open( } hEncoderConfig = st_ivas->hEncoderConfig; + generate_gridEq( &( hMasa->data.Sph_Grid16 ) ); +#ifdef MASA_AND_OBJECTS + if ( hEncoderConfig->ivas_format == MASA_FORMAT || hEncoderConfig->ivas_format == MASA_ISM_FORMAT ) +#else if ( hEncoderConfig->ivas_format == MASA_FORMAT ) +#endif { hMasa->data.num_Cldfb_instances = st_ivas->nchan_transport; } @@ -126,7 +141,23 @@ ivas_error ivas_masa_enc_open( } } - ivas_masa_set_elements( st_ivas->hEncoderConfig->ivas_total_brate, st_ivas->mc_mode, st_ivas->nchan_transport, st_ivas->hQMetaData, &hEncoderConfig->element_mode_init, &st_ivas->nSCE, &st_ivas->nCPE ); +#ifdef MASA_AND_OBJECTS + ism_total_brate = 0; + if ( hEncoderConfig->ivas_format == MASA_ISM_FORMAT && st_ivas->nSCE > 0 && ( st_ivas->ism_mode == ISM_MASA_MODE_DISC || st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) ) + { + for ( i = 0; i < st_ivas->nSCE; i++ ) + { + ism_total_brate += st_ivas->hSCE[i]->element_brate; + } + } +#endif + + ivas_masa_set_elements( st_ivas->hEncoderConfig->ivas_total_brate, st_ivas->mc_mode, st_ivas->nchan_transport, st_ivas->hQMetaData, &hEncoderConfig->element_mode_init, &st_ivas->nSCE, &st_ivas->nCPE +#ifdef MASA_AND_OBJECTS + , + hEncoderConfig->ivas_format, st_ivas->ism_mode, ism_total_brate +#endif + ); mvs2s( DirAC_block_grouping, hMasa->config.block_grouping, MAX_PARAM_SPATIAL_SUBFRAMES + 1 ); mvs2s( MASA_band_grouping_24, hMasa->config.band_grouping, MASA_FREQUENCY_BANDS + 1 ); @@ -148,6 +179,12 @@ ivas_error ivas_masa_enc_open( set_zero( hMasa->data.dir_align_state.previous_azi_dir2, MASA_FREQUENCY_BANDS ); set_zero( hMasa->data.dir_align_state.previous_ele_dir2, MASA_FREQUENCY_BANDS ); +#ifdef MASA_AND_OBJECTS + hMasa->data.lp_noise_CPE = -1; + hMasa->data.omasa_stereo_sw_cnt = OMASA_STEREO_SW_CNT_MAX; + hMasa->data.omasa_stereo_sw_cnt2 = OMASA_STEREO_SW_CNT_MAX2; +#endif + st_ivas->hMasa = hMasa; return error; @@ -199,16 +236,36 @@ ivas_error ivas_masa_encode( const int32_t ivas_total_brate, /* i : IVAS total bitrate */ const int16_t Opt_DTX_ON, /* i : DTX on flag */ const int16_t element_mode /* i : element mode */ +#ifdef MASA_AND_OBJECTS + , + const ISM_MODE ism_mode, /* i : ISM format mode */ + const int16_t nchan_ism, /* i : number of ISM channels */ + ISM_METADATA_HANDLE hIsmMetaData[MAX_NUM_OBJECTS], /* i : ISM metadata handle */ + const int16_t idx_separated_object, /* i : index of the separated object */ + OMASA_ENC_HANDLE hOMasa, /* i : OMASA encoder handle */ + const int16_t ism_imp /* i : importance of separated object */ + , + const int16_t flag_omasa_ener_brate /* i : less bitrate for objects in OMASA flag */ +#endif ) { MASA_DIRECTIONAL_SPATIAL_META *h_orig_metadata; int16_t i, j; int16_t masa_sid_descriptor; +#ifdef MASA_AND_OBJECTS + int16_t low_bitrate_mode; + int32_t masa_total_brate; +#endif masa_sid_descriptor = -1; h_orig_metadata = NULL; +#ifdef MASA_AND_OBJECTS + low_bitrate_mode = 0; + if ( ivas_format == MASA_FORMAT || ivas_format == MASA_ISM_FORMAT ) +#else if ( ivas_format == MASA_FORMAT ) +#endif { /* Create the MASA SID descriptor for the metadata and CPE mode, in order to have the SID frame self-contained. */ if ( Opt_DTX_ON && hQMetaData != NULL ) @@ -245,7 +302,11 @@ ivas_error ivas_masa_encode( } } - if ( ivas_format == MASA_FORMAT && ivas_total_brate >= IVAS_384k ) +#ifdef MASA_AND_OBJECTS + if ( ( ivas_format == MASA_FORMAT || ivas_format == MASA_ISM_FORMAT ) && ivas_total_brate >= IVAS_384k ) +#else + if ( ( ivas_format == MASA_FORMAT ) && ivas_total_brate >= IVAS_384k ) +#endif { hMasa->config.mergeRatiosOverSubframes = 0; } @@ -254,10 +315,22 @@ ivas_error ivas_masa_encode( combine_freqbands_and_subframes( hMasa ); } +#ifdef MASA_AND_OBJECTS + if ( hMasa->config.numberOfDirections == 2 && hMasa->config.numTwoDirBands < hMasa->config.numCodingBands && ( ivas_format == MASA_FORMAT || ivas_format == MASA_ISM_FORMAT ) ) +#else if ( hMasa->config.numberOfDirections == 2 && hMasa->config.numTwoDirBands < hMasa->config.numCodingBands && ivas_format == MASA_FORMAT ) +#endif { +#ifdef MASA_AND_OBJECTS + if ( ( ivas_format == MASA_ISM_FORMAT && ism_mode != ISM_MODE_NONE && ism_mode != ISM_MASA_MODE_MASA_ONE_OBJ ) || ( ivas_format != MASA_ISM_FORMAT ) ) + { + /* Combine directions */ + ivas_masa_combine_directions( hMasa ); + } +#else /* Combine directions */ combine_directions( hMasa ); +#endif /* If we joined all bands, then metadata is now one directional. */ if ( hMasa->config.numTwoDirBands == 0 ) @@ -270,12 +343,140 @@ ivas_error ivas_masa_encode( /* Reset qmetadata bit budget */ hQMetaData->metadata_max_bits = hMasa->config.max_metadata_bits; - +#ifdef MASA_AND_OBJECTS + if ( ivas_format == MASA_FORMAT || ivas_format == MASA_ISM_FORMAT ) +#else if ( ivas_format == MASA_FORMAT ) +#endif { +#ifndef MASA_AND_OBJECTS /* write the number of MASA transport channels */ push_next_indice( hMetaData, nchan_transport - 1, MASA_TRANSP_BITS ); hQMetaData->metadata_max_bits -= MASA_TRANSP_BITS; +#endif +#ifdef MASA_AND_OBJECTS + if ( ivas_format == MASA_ISM_FORMAT && ism_mode != ISM_MODE_NONE ) + { + /* write the number of objects in ISM_MASA format*/ + push_next_indice( hMetaData, nchan_ism - 1, NO_BITS_MASA_ISM_NO_OBJ ); + hQMetaData->metadata_max_bits -= NO_BITS_MASA_ISM_NO_OBJ; + + /* write index of separated object if needed */ + if ( ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ && hMasa->data.nchan_ism > 1 ) + { + push_next_indice( hMetaData, idx_separated_object, NO_BITS_MASA_ISM_NO_OBJ ); + hQMetaData->metadata_max_bits -= NO_BITS_MASA_ISM_NO_OBJ; + } + + /* write ISM importance flag (one per object) */ + if ( ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) + { + push_next_indice( hMetaData, hIsmMetaData[0]->ism_imp, ISM_METADATA_FLAG_BITS ); + hQMetaData->metadata_max_bits -= ISM_METADATA_FLAG_BITS; + } + else if ( ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) + { +#ifdef MASA_AND_OBJECTS + if ( hIsmMetaData[0]->ism_md_null_flag ) + { + /* signal NULL metadata frame */ + push_next_indice( hMetaData, 1, ISM_METADATA_MD_FLAG_BITS ); + hQMetaData->metadata_max_bits -= ISM_METADATA_MD_FLAG_BITS; + + /* write the ISM class to ISM_NO_META and again the true ISM class */ + push_next_indice( hMetaData, ISM_NO_META, ISM_METADATA_FLAG_BITS ); + hQMetaData->metadata_max_bits -= ISM_METADATA_FLAG_BITS; + push_next_indice( hMetaData, hIsmMetaData[0]->ism_imp, ISM_METADATA_FLAG_BITS ); + hQMetaData->metadata_max_bits -= ISM_METADATA_FLAG_BITS; + } + else + { + push_next_indice( hMetaData, hIsmMetaData[0]->ism_imp, ISM_METADATA_FLAG_BITS ); + hQMetaData->metadata_max_bits -= ISM_METADATA_FLAG_BITS; + + if ( hIsmMetaData[0]->ism_imp == ISM_NO_META ) + { + /* signal low-rate ISM_NO_META frame */ + push_next_indice( hMetaData, 0, ISM_METADATA_MD_FLAG_BITS ); + hQMetaData->metadata_max_bits -= ISM_METADATA_MD_FLAG_BITS; + + /* signal presence of MD in low-rate ISM_NO_META frame */ + push_next_indice( hMetaData, hIsmMetaData[0]->ism_md_lowrate_flag, ISM_METADATA_INACTIVE_FLAG_BITS ); + hQMetaData->metadata_max_bits -= ISM_METADATA_INACTIVE_FLAG_BITS; + } + } +#else + push_next_indice( hMetaData, hIsmMetaData[0]->ism_imp, ISM_METADATA_FLAG_BITS ); + hQMetaData->metadata_max_bits -= ISM_METADATA_FLAG_BITS; + + if ( hIsmMetaData[0]->ism_metadata_flag == 0 ) + { + /* write VAD flag */ + push_next_indice( hMetaData, hIsmMetaData[0]->ism_vad_flag, ISM_METADATA_VAD_FLAG_BITS ); + hQMetaData->metadata_max_bits -= ISM_METADATA_VAD_FLAG_BITS; + } +#endif + } + else if ( ism_mode == ISM_MASA_MODE_DISC ) + { + for ( i = 0; i < nchan_ism; i++ ) + { +#ifdef MASA_AND_OBJECTS + if ( hIsmMetaData[i]->ism_md_null_flag ) + { + /* signal NULL metadata frame */ + push_next_indice( hMetaData, 1, ISM_METADATA_MD_FLAG_BITS ); + hQMetaData->metadata_max_bits -= ISM_METADATA_MD_FLAG_BITS; + + /* write the ISM class to ISM_NO_META and again the true ISM class */ + push_next_indice( hMetaData, ISM_NO_META, ISM_METADATA_FLAG_BITS ); + hQMetaData->metadata_max_bits -= ISM_METADATA_FLAG_BITS; + push_next_indice( hMetaData, hIsmMetaData[i]->ism_imp, ISM_METADATA_FLAG_BITS ); + hQMetaData->metadata_max_bits -= ISM_METADATA_FLAG_BITS; + } + else + { + push_next_indice( hMetaData, hIsmMetaData[i]->ism_imp, ISM_METADATA_FLAG_BITS ); + hQMetaData->metadata_max_bits -= ISM_METADATA_FLAG_BITS; + + if ( hIsmMetaData[i]->ism_imp == ISM_NO_META ) + { + /* signal low-rate ISM_NO_META frame */ + push_next_indice( hMetaData, 0, ISM_METADATA_MD_FLAG_BITS ); + hQMetaData->metadata_max_bits -= ISM_METADATA_MD_FLAG_BITS; + + /* signal presence of MD in low-rate ISM_NO_META frame */ + push_next_indice( hMetaData, hIsmMetaData[i]->ism_md_lowrate_flag, ISM_METADATA_INACTIVE_FLAG_BITS ); + hQMetaData->metadata_max_bits -= ISM_METADATA_INACTIVE_FLAG_BITS; + } + } +#else + push_next_indice( hMetaData, hIsmMetaData[i]->ism_imp, ISM_METADATA_FLAG_BITS ); + hQMetaData->metadata_max_bits -= ISM_METADATA_FLAG_BITS; + + if ( hIsmMetaData[i]->ism_metadata_flag == 0 ) + { + /* write VAD flag */ + push_next_indice( hMetaData, hIsmMetaData[i]->ism_vad_flag, ISM_METADATA_VAD_FLAG_BITS ); + hQMetaData->metadata_max_bits -= ISM_METADATA_VAD_FLAG_BITS; + } +#endif + } + + if ( ivas_total_brate == IVAS_128k && nchan_ism >= 3 ) + { + push_next_indice( hMetaData, flag_omasa_ener_brate, 1 ); + hQMetaData->metadata_max_bits -= 1; + } + } + } + else + { + /* write the number of MASA transport channels */ + push_next_indice( hMetaData, nchan_transport - 1, MASA_TRANSP_BITS ); + hQMetaData->metadata_max_bits -= MASA_TRANSP_BITS; + } +#endif /* write placeholder data for descriptive metadata */ push_next_indice( hMetaData, 0, MASA_HEADER_BITS ); @@ -298,21 +499,64 @@ ivas_error ivas_masa_encode( } /* Move data from encoder to qmetadata */ +#ifdef MASA_AND_OBJECTS + if ( ivas_format == MASA_FORMAT || ivas_format == MASA_ISM_FORMAT ) +#else if ( ivas_format == MASA_FORMAT ) +#endif { move_metadata_to_qmetadata( hMasa, hQMetaData ); } if ( hMasa->config.max_metadata_bits < MINIMUM_BIT_BUDGET_NORMAL_META && !hMasa->config.joinedSubframes ) { +#ifdef MASA_AND_OBJECTS reduce_metadata_further( hMasa, hQMetaData, ivas_format ); + low_bitrate_mode = ( ivas_total_brate <= 32000 ); +#else + reduce_metadata_further( hMasa, hQMetaData, ivas_format ); +#endif + /* Write low bitrate mode. 1 signals that we have merged through time, 0 signals merge through frequency. */ push_next_indice( hMetaData, hQMetaData->q_direction[0].cfg.nblocks == 1 ? 1 : 0, MASA_LOWBITRATE_MODE_BITS ); hQMetaData->metadata_max_bits -= MASA_LOWBITRATE_MODE_BITS; } +#ifdef MASA_AND_OBJECTS + /* Encode MASA+ISM metadata */ + if ( ivas_format == MASA_ISM_FORMAT && ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) + { + /* encode MASA/ISM energy ratios */ + ivas_encode_masaism_metadata( hMasa, hQMetaData, hMetaData, hIsmMetaData, low_bitrate_mode, hOMasa->nCodingBands, hOMasa->nSubframes, + idx_separated_object, ism_imp ); + } + else + { + hQMetaData->masa_to_total_energy_ratio[0][0] = -1; /* signals NOT to adjust the energy ratios */ + } +#endif + /* Encode metadata */ +#ifdef MASA_AND_OBJECTS + masa_total_brate = ivas_total_brate; + if ( ivas_format == MASA_ISM_FORMAT && ism_mode == ISM_MASA_MODE_DISC ) + { + masa_total_brate = calculate_cpe_brate_MASA_ISM( ism_mode, ivas_total_brate, nchan_ism ); + } + + if ( masa_total_brate >= IVAS_384k ) + { + if ( masa_total_brate >= IVAS_512k ) + { + ivas_qmetadata_enc_encode_hr_384_512( hMetaData, hQMetaData, 16, 4 ); + } + else + { + ivas_qmetadata_enc_encode_hr_384_512( hMetaData, hQMetaData, 11, 3 ); + } + } +#else if ( ivas_total_brate >= IVAS_384k ) { if ( ivas_total_brate >= IVAS_512k ) @@ -324,11 +568,20 @@ ivas_error ivas_masa_encode( ivas_qmetadata_enc_encode_hr_384_512( hMetaData, hQMetaData, 11, 3 ); } } +#endif else { ivas_qmetadata_enc_encode( hMetaData, hQMetaData, 0 ); } +#ifdef MASA_AND_OBJECTS + if ( ivas_format == MASA_ISM_FORMAT && ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) + { + /* Modify spatial metadata based on the MASA-to-total energy ratios */ + modify_masa_energy_ratios( hQMetaData ); + } + +#endif *nb_bits_metadata = hMetaData->nb_bits_tot; if ( ivas_format == MASA_FORMAT && Opt_DTX_ON ) @@ -362,7 +615,11 @@ ivas_error ivas_masa_encode( if ( hMasa->config.numberOfDirections == 2 && hMasa->config.numTwoDirBands < hMasa->config.numCodingBands ) { /* Combine directions */ +#ifdef MASA_AND_OBJECTS + ivas_masa_combine_directions( hMasa ); +#else combine_directions( hMasa ); +#endif /* If we joined all bands, then metadata is now one directional. */ if ( hMasa->config.numTwoDirBands == 0 ) @@ -486,6 +743,12 @@ ivas_error ivas_masa_enc_config( uint8_t maxBand; int16_t maxBin, sf; ivas_error error; +#ifdef MASA_AND_OBJECTS + int32_t ism_total_brate; +#ifdef OMASA_FIX_LOW_FS + int32_t masa_total_brate; +#endif +#endif error = IVAS_ERR_OK; @@ -494,10 +757,30 @@ ivas_error ivas_masa_enc_config( ivas_format = st_ivas->hEncoderConfig->ivas_format; ivas_total_brate = st_ivas->hEncoderConfig->ivas_total_brate; - ivas_masa_set_elements( ivas_total_brate, st_ivas->mc_mode, st_ivas->nchan_transport, hQMetaData, &st_ivas->hEncoderConfig->element_mode_init, &st_ivas->nSCE, &st_ivas->nCPE ); +#ifdef MASA_AND_OBJECTS + ism_total_brate = 0; + if ( ivas_format == MASA_ISM_FORMAT && st_ivas->nSCE > 0 && ( st_ivas->ism_mode == ISM_MASA_MODE_DISC || st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) ) + { + for ( i = 0; i < st_ivas->nSCE; i++ ) + { + ism_total_brate += st_ivas->hSCE[i]->element_brate; + } + } +#endif + + ivas_masa_set_elements( ivas_total_brate, st_ivas->mc_mode, st_ivas->nchan_transport, hQMetaData, &st_ivas->hEncoderConfig->element_mode_init, &st_ivas->nSCE, &st_ivas->nCPE +#ifdef MASA_AND_OBJECTS + , + ivas_format, st_ivas->ism_mode, ism_total_brate +#endif + ); hQMetaData->is_masa_ivas_format = 1; +#ifdef MASA_AND_OBJECTS + if ( ivas_format == MASA_FORMAT || ivas_format == MASA_ISM_FORMAT ) +#else if ( ivas_format == MASA_FORMAT ) +#endif { masa_metadata_direction_alignment( hMasa ); @@ -522,7 +805,18 @@ ivas_error ivas_masa_enc_config( hMasa->config.numberOfDirections = 1; } - ivas_masa_set_coding_config( &( hMasa->config ), hMasa->data.band_mapping, ivas_total_brate, st_ivas->nchan_transport, ( ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCMASA ) ); +#ifdef MASA_AND_OBJECTS + if ( ivas_format == MASA_ISM_FORMAT ) + { + ivas_masa_set_coding_config( &( hMasa->config ), hMasa->data.band_mapping, st_ivas->hCPE[0]->element_brate, st_ivas->nchan_transport, MC_MODE_NONE ); + } + else + { +#endif + ivas_masa_set_coding_config( &( hMasa->config ), hMasa->data.band_mapping, ivas_total_brate, st_ivas->nchan_transport, ( ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCMASA ) ); +#ifdef MASA_AND_OBJECTS + } +#endif /* Setup importance weights for two-direction band selection. */ if ( hMasa->config.numberOfDirections == 2 ) @@ -607,7 +901,21 @@ ivas_error ivas_masa_enc_config( } maxBand--; +#ifdef MASA_AND_OBJECTS + st_ivas->hQMetaData->q_direction->cfg.inactiveBands = 0; +#ifdef OMASA_FIX_LOW_FS + masa_total_brate = ivas_total_brate; + if ( ivas_format == MASA_ISM_FORMAT && st_ivas->ism_mode == ISM_MASA_MODE_DISC ) + { + masa_total_brate = calculate_cpe_brate_MASA_ISM( st_ivas->ism_mode, ivas_total_brate, st_ivas->hEncoderConfig->nchan_ism ); + } + if ( masa_total_brate >= IVAS_384k && ( ivas_format == MASA_FORMAT || ivas_format == MASA_ISM_FORMAT ) ) +#else + if ( ivas_total_brate > IVAS_256k && ivas_format == MASA_FORMAT ) +#endif +#else if ( ivas_total_brate > IVAS_256k ) +#endif { int16_t continueLoop; continueLoop = 1; @@ -636,8 +944,12 @@ ivas_error ivas_masa_enc_config( st_ivas->hQMetaData->q_direction->cfg.inactiveBands = 0; } } +#ifdef OMASA_FIX_LOW_FS + masa_sample_rate_band_correction( &( hMasa->config ), hMasa->data.band_mapping, hQMetaData, maxBand, masa_total_brate >= IVAS_384k, NULL ); +#else masa_sample_rate_band_correction( &( hMasa->config ), hMasa->data.band_mapping, hQMetaData, maxBand, ivas_total_brate > IVAS_256k, NULL ); +#endif if ( hMasa->config.numTwoDirBands >= hMasa->config.numCodingBands ) { @@ -647,10 +959,32 @@ ivas_error ivas_masa_enc_config( /* Transmit stereo signals using a mono downmix at lowest bitrates */ +#ifdef MASA_AND_OBJECTS + if ( ( ivas_format == MASA_FORMAT || ivas_format == MASA_ISM_FORMAT ) && st_ivas->nCPE == 1 && st_ivas->hCPE[0]->hStereoDft != NULL && st_ivas->hCPE[0]->hStereoDft->hConfig != NULL ) +#else if ( ivas_format == MASA_FORMAT && st_ivas->nCPE == 1 && st_ivas->hCPE[0]->hStereoDft != NULL && st_ivas->hCPE[0]->hStereoDft->hConfig != NULL ) +#endif { +#ifdef MASA_AND_OBJECTS + st_ivas->hCPE[0]->hStereoDft->hConfig->force_mono_transmission = ( ivas_total_brate - ism_total_brate < MASA_STEREO_MIN_BITRATE ) ? 1 : 0; +#else st_ivas->hCPE[0]->hStereoDft->hConfig->force_mono_transmission = ivas_total_brate < MASA_STEREO_MIN_BITRATE ? 1 : 0; +#endif + } + +#ifdef MASA_AND_OBJECTS + if ( ivas_format == MASA_ISM_FORMAT && ( st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_DISC ) ) + { + if ( st_ivas->hCPE[0]->element_mode == IVAS_CPE_DFT || st_ivas->hMasa->data.omasa_stereo_sw_cnt < OMASA_STEREO_SW_CNT_MAX ) + { + st_ivas->hMasa->data.lp_noise_CPE = st_ivas->hCPE[0]->hCoreCoder[0]->lp_noise; + } + else + { + st_ivas->hMasa->data.lp_noise_CPE = ( st_ivas->hCPE[0]->hCoreCoder[0]->lp_noise + st_ivas->hCPE[0]->hCoreCoder[1]->lp_noise ) / CPE_CHANNELS; + } } +#endif return error; } @@ -886,8 +1220,11 @@ static void combine_freqbands_and_subframes( return; } - +#ifdef MASA_AND_OBJECTS +void ivas_masa_combine_directions( +#else static void combine_directions( +#endif MASA_ENCODER_HANDLE hMasa ) { int16_t i, j, k; @@ -1003,7 +1340,9 @@ static void combine_directions( ambience2dir = 1.0f - ratioSum; hMeta->directional_meta[0].energy_ratio[j][i] = sumVecLen[j][i] / ( hMeta->directional_meta[0].energy_ratio[j][i] + hMeta->directional_meta[1].energy_ratio[j][i] + ambience2dir / 2.0f ); - +#ifdef MASA_AND_OBJECTS + hMeta->directional_meta[1].energy_ratio[j][i] = 0.0f; +#endif if ( computeCoherence ) { ambience1dir = 1.0f - hMeta->directional_meta[0].energy_ratio[j][i]; @@ -1338,7 +1677,11 @@ static void reduce_metadata_further( /* Get energy for the input data in 4-subframe, 5-band format */ totalEnergySum = 0.0f; +#ifdef MASA_AND_OBJECTS + if ( ivas_format == MASA_FORMAT || ivas_format == MASA_ISM_FORMAT ) /* Energy data is in 4-subframe, 24-band format */ +#else if ( ivas_format == MASA_FORMAT ) /* Energy data is in 4-subframe, 24-band format */ +#endif { for ( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ ) { @@ -1717,9 +2060,23 @@ void ivas_masa_enc_reconfigure( int16_t n, tmp; int16_t sce_id, cpe_id; int32_t ivas_total_brate; +#ifdef MASA_AND_OBJECTS + int32_t ism_total_brate; +#endif ivas_total_brate = st_ivas->hEncoderConfig->ivas_total_brate; +#ifdef MASA_AND_OBJECTS + ism_total_brate = 0; + if ( st_ivas->hEncoderConfig->ivas_format == MASA_ISM_FORMAT && st_ivas->nSCE > 0 && ( st_ivas->ism_mode == ISM_MASA_MODE_DISC || st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) ) + { + for ( sce_id = 0; sce_id < st_ivas->nSCE; sce_id++ ) + { + ism_total_brate += st_ivas->hSCE[sce_id]->element_brate; + } + } +#endif + if ( ivas_total_brate != st_ivas->hEncoderConfig->last_ivas_total_brate ) { for ( sce_id = 0; sce_id < st_ivas->nSCE; sce_id++ ) @@ -1740,6 +2097,16 @@ void ivas_masa_enc_reconfigure( st_ivas->hCPE[cpe_id]->hCoreCoder[n]->total_brate = st_ivas->hCPE[cpe_id]->element_brate / ( st_ivas->nCPE > 1 ? 1 : CPE_CHANNELS ); /* dummy initialization for getting right pointers initialization of input buffers in init_coder_ace_plus() */ } +#ifdef MASA_AND_OBJECTS + if ( ivas_total_brate - ism_total_brate < MASA_STEREO_MIN_BITRATE || ivas_total_brate - ism_total_brate < MIN_BRATE_MDCT_STEREO ) + { + st_ivas->hCPE[cpe_id]->element_mode = IVAS_CPE_DFT; + } + else + { + st_ivas->hCPE[cpe_id]->element_mode = IVAS_CPE_MDCT; + } +#else if ( ivas_total_brate < MASA_STEREO_MIN_BITRATE ) { st_ivas->hCPE[cpe_id]->element_mode = IVAS_CPE_DFT; @@ -1752,9 +2119,15 @@ void ivas_masa_enc_reconfigure( { st_ivas->hCPE[cpe_id]->element_mode = IVAS_CPE_MDCT; } +#endif } - ivas_masa_set_elements( ivas_total_brate, st_ivas->mc_mode, st_ivas->nchan_transport, st_ivas->hQMetaData, &tmp, &tmp, &tmp ); + ivas_masa_set_elements( ivas_total_brate, st_ivas->mc_mode, st_ivas->nchan_transport, st_ivas->hQMetaData, &tmp, &tmp, &tmp +#ifdef MASA_AND_OBJECTS + , + st_ivas->hEncoderConfig->ivas_format, st_ivas->ism_mode, ism_total_brate +#endif + ); } return; @@ -1943,11 +2316,12 @@ static void copy_masa_metadata( * Compare the similarity of MASA metadata in two sub-frames *-------------------------------------------------------------------*/ +/* r: similarity decision */ static uint8_t are_masa_subframes_similar( const MASA_METADATA_HANDLE frame1, /* i : MASA metadata frame 1 */ const uint8_t sf1_idx, /* i : index of the subframe of frame1 to inspect */ const MASA_METADATA_HANDLE frame2, /* i : MASA metadata frame 2 */ - const uint8_t sf2_idx /* o : index of the subframe of frame2 to inspect */ + const uint8_t sf2_idx /* i : index of the subframe of frame2 to inspect */ ) { uint8_t num_dir; @@ -2130,7 +2504,7 @@ static void detect_framing_async( else if ( n_sim_stop == 3 ) { /* first sub-frame different that the rest 3 - => make a risky guess that the future sf would be the same too and we're in an offset case */ + => make a risky guess that the future sf would be the same too and we're in an offset case */ frame_mode = MASA_FRAME_1SF; found_offset = 3; } @@ -2328,3 +2702,1106 @@ static void masa_metadata_direction_alignment( return; } + + +#ifdef MASA_AND_OBJECTS +/*-------------------------------------------------------------------* + * ivas_merge_masa_metadata() + * + * + *-------------------------------------------------------------------*/ + +void ivas_merge_masa_metadata( + MASA_ENCODER_HANDLE hMasa, /* i/o: MASA enc handle. source for MASA metadata and combined metadata will be here */ + OMASA_SPATIAL_META_HANDLE hOMasaMeta /* i : ISM-object metadata to be merged with the MASA metadata */ +) +{ + int16_t sf, band; + uint8_t numCodingBands; + uint8_t numDirections; + uint8_t numSf; + MASA_METADATA_HANDLE hMeta; + float energyTimesRatioISM; + float energyTimesRatioMASA[2]; + float total_diff_nrg; + int16_t brange[2]; + float eneBand; + float energyMerged[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; + int16_t bin; + + numCodingBands = hMasa->config.numCodingBands; + numDirections = hMasa->config.numberOfDirections; + numSf = hMasa->config.joinedSubframes == TRUE ? 1 : 4; + hMeta = &( hMasa->masaMetadata ); + + + for ( sf = 0; sf < numSf; sf++ ) + { + for ( band = 0; band < numCodingBands; band++ ) + { + int16_t merge_dest; + float dir_sum; + uint8_t band_n_dirs; + brange[0] = band; + brange[1] = band + 1; + /* TODO: if this stays, remove the unnecessary range loop from the code */ + if ( numDirections == 1 || ( numDirections == 2 && hMasa->data.twoDirBands[band] == 0 ) ) + { + band_n_dirs = 1; + } + else + { + band_n_dirs = 2; + } + + /* Compute energies */ + /* MASA energy is in the full 24 band resolution, whereas the ISM energy is already in the coding band resolution */ + eneBand = 0.0f; + for ( bin = brange[0]; bin < brange[1]; bin++ ) + { + eneBand += hMasa->data.energy[sf][bin]; + } + energyMerged[sf][band] = eneBand + hMasa->data.energy_ism[sf][band]; + + /* Compute weights */ + energyTimesRatioMASA[0] = eneBand * hMeta->directional_meta[0].energy_ratio[sf][band]; + if ( band_n_dirs == 2 ) + { + energyTimesRatioMASA[1] = eneBand * hMeta->directional_meta[1].energy_ratio[sf][band]; + } + else + { + energyTimesRatioMASA[1] = 0.0f; + } + /* target is original MASA diffuseness */ + total_diff_nrg = eneBand * hMeta->common_meta.diffuse_to_total_ratio[sf][band]; + /* criterion is mean of ISM ratio and new ratio */ + energyTimesRatioISM = ( hOMasaMeta->directional_meta[0].energy_ratio[sf][band] + ( 1.0f - total_diff_nrg / ( EPSILON + eneBand + hMasa->data.energy_ism[sf][band] ) ) ) / 2.0f * hMasa->data.energy_ism[sf][band]; + + /* Determine combined metadata based on the weights */ + merge_dest = -1; + if ( ( band_n_dirs == 1 && energyTimesRatioMASA[0] < energyTimesRatioISM ) || + ( band_n_dirs == 2 && energyTimesRatioMASA[0] < energyTimesRatioMASA[1] && energyTimesRatioMASA[0] < energyTimesRatioISM ) ) + { + /* 1dir and ISM the most energetic, or 2dir and ISM the more energetic than MASA1 */ + merge_dest = 0; + } + else if ( band_n_dirs == 2 && energyTimesRatioMASA[1] <= energyTimesRatioMASA[0] && energyTimesRatioMASA[1] < energyTimesRatioISM ) + { + /* 2dir and ISM the most energetic and MASA2 the least energetic */ + merge_dest = 1; + } + + if ( merge_dest >= 0 ) /* replace one MASA with ISM */ + { + hMeta->directional_meta[merge_dest].azimuth[sf][band] = hOMasaMeta->directional_meta[0].azimuth[sf][band]; + hMeta->directional_meta[merge_dest].elevation[sf][band] = hOMasaMeta->directional_meta[0].elevation[sf][band]; + /* limit with the earlier direct-energy ratio */ + dir_sum = 1.0f - total_diff_nrg / ( EPSILON + eneBand + hMasa->data.energy_ism[sf][band] ); /* new dir ratio */ + hMeta->directional_meta[merge_dest].energy_ratio[sf][band] = min( dir_sum, hOMasaMeta->directional_meta[0].energy_ratio[sf][band] ); /* clip with original ISM dir */ + hMeta->common_meta.diffuse_to_total_ratio[sf][band] = 1.0f - hMeta->directional_meta[merge_dest].energy_ratio[sf][band]; + + if ( hMasa->config.useCoherence ) /* TODO: is this correct condition? */ + { + hMeta->directional_meta[merge_dest].spread_coherence[sf][band] = hOMasaMeta->directional_meta[0].spread_coherence[sf][band]; + hMeta->common_meta.surround_coherence[sf][band] = hOMasaMeta->common_meta.surround_coherence[sf][band]; + } + + /* recompute direct energy ratios to match the diffuse ratio */ + float direct_quota, direct_scaler; + direct_quota = 1.0f - hMeta->common_meta.diffuse_to_total_ratio[sf][band]; + if ( band_n_dirs == 1 ) + { + hMeta->directional_meta[0].energy_ratio[sf][band] = direct_quota; + } + else + { + dir_sum = hMeta->directional_meta[0].energy_ratio[sf][band] + hMeta->directional_meta[1].energy_ratio[sf][band]; + direct_scaler = direct_quota / ( EPSILON + dir_sum ); + hMeta->directional_meta[0].energy_ratio[sf][band] *= direct_scaler; + hMeta->directional_meta[1].energy_ratio[sf][band] *= direct_scaler; + } + } + } + } + + for ( sf = 0; sf < numSf; sf++ ) + { + for ( band = 0; band < numCodingBands; band++ ) + { + hMasa->data.energy[sf][band] = energyMerged[sf][band]; + } + } + + return; +} + + +static void quantize_ratio_ism_vector( + const float *ratio_ism, + int16_t *idx, + const int16_t nchan_ism, + const float masa_to_total_energy_ratio, + const int16_t idx_sep_object ) +{ + int16_t i, j, best_i, best_i2; + float dist, div, tmp, dist2, best_dist; + int16_t part_idx_sum, max_sum_idx; + float ratio_ism_loc[MAX_NUM_OBJECTS]; + int16_t no_ism_loc; + + max_sum_idx = ( 1 << PARAM_ISM_POW_RATIO_NBITS ) - 1; + + if ( idx_sep_object > -1 ) + { + if ( ratio_ism[idx_sep_object] < 1.0f / (float) ( max_sum_idx ) ) + { + /* take it out from quantize function */ + mvr2r( ratio_ism, ratio_ism_loc, idx_sep_object ); + mvr2r( &ratio_ism[idx_sep_object + 1], &ratio_ism_loc[idx_sep_object], nchan_ism - idx_sep_object - 1 ); + no_ism_loc = nchan_ism - 1; + } + else + { + no_ism_loc = nchan_ism; + mvr2r( ratio_ism, ratio_ism_loc, nchan_ism ); + } + } + else + { + no_ism_loc = nchan_ism; + mvr2r( ratio_ism, ratio_ism_loc, nchan_ism ); + } + + if ( nchan_ism > 1 ) + { + if ( masa_to_total_energy_ratio >= MASA2TOTAL_THR ) + { + distribute_evenly_ism( idx, max_sum_idx, nchan_ism ); + } + else + { + if ( no_ism_loc > 1 ) + { + + dist = 0.0f; + div = 1.0f / (float) ( max_sum_idx ); + + part_idx_sum = 0; + + for ( i = 0; i < no_ism_loc; i++ ) + { + idx[i] = (int16_t) ( ( ratio_ism_loc[i] ) * ( max_sum_idx ) ); + part_idx_sum += idx[i]; + + tmp = ( ratio_ism_loc[i] - ( idx[i] * div ) ); + dist += ( tmp * tmp ); + } + + best_dist = dist; + best_i2 = -1; + while ( part_idx_sum < max_sum_idx ) + { + best_i = -1; + /* check which index to increase by 1 for a possible improvement */ + + for ( i = 0; i < no_ism_loc; i++ ) + { + idx[i]++; + dist2 = 0.0f; + + for ( j = 0; j < no_ism_loc; j++ ) + { + tmp = ( ratio_ism_loc[i] - ( idx[i] * div ) ); + dist2 += ( tmp * tmp ); + } + + if ( dist2 < best_dist ) + { + best_i2 = best_i; + best_i = i; + best_dist = dist2; + } + idx[i]--; + } + if ( best_i > -1 ) + { + idx[best_i]++; + part_idx_sum++; + } + else + { + if ( best_i2 > -1 ) + { + idx[best_i2]++; + part_idx_sum++; + } + else + { + idx[no_ism_loc - 1] += max_sum_idx - part_idx_sum; + part_idx_sum = max_sum_idx; + } + } + } + assert( sum_s( idx, no_ism_loc ) == max_sum_idx ); + } + else + { + idx[0] = max_sum_idx; + } + + if ( no_ism_loc < nchan_ism ) + { + /* insert back the ratio of the separated object */ + for ( i = nchan_ism - 1; i > idx_sep_object; i-- ) + { + idx[i] = idx[i - 1]; + } + idx[idx_sep_object] = 0; + } + } + } + else + { + idx[0] = (int16_t) ( ( ratio_ism[0] ) * ( ( 1 << PARAM_ISM_POW_RATIO_NBITS ) - 1 ) + 0.5f ); + } + + return; +} + + +static int16_t index_slice_enum( + const int16_t *ratio_ism_idx, + const int16_t nchan_ism ) +{ + int16_t i; + int16_t x, index; + int16_t base; + + if ( nchan_ism == 2 ) + { + index = ratio_ism_idx[0]; + } + else + { + x = ratio_ism_idx[nchan_ism - 2]; + base = 10; + for ( i = nchan_ism - 3; i >= 0; i-- ) + { + x += ratio_ism_idx[i] * base; + base *= 10; + } + + index = 0; + i = 0; + while ( i <= x ) + { + if ( valid_ratio_index( i, 7, nchan_ism - 1 ) ) + { + index++; + } + i++; + } + index--; + } + + return index; +} + + +static void transform_difference_index( + const int16_t *diff_idx, + int16_t *idx, + const int16_t len ) +{ + int16_t i; + for ( i = 0; i < len; i++ ) + { + if ( diff_idx[i] <= 0 ) + { + idx[i] = -2 * diff_idx[i]; + } + else + { + idx[i] = 2 * diff_idx[i] - 1; + } + } + + return; +} + + +static void transform_index_and_GR_encode( + int16_t *diff_idx, /* i : differenc eindex to encode */ + const int16_t len, /* i : input length */ + const int16_t GR_order, /* i : GR order */ + BSTR_ENC_HANDLE hMetaData /* i/o: metadata bitstream handle */ +) +{ + int16_t i; + int16_t idx[IVAS_MAX_NUM_OBJECTS]; + + /* transform difference index into positive */ + transform_difference_index( diff_idx, idx, len ); + + /* GR encoding */ + for ( i = 0; i < len; i++ ) + { + ivas_qmetadata_encode_extended_gr( hMetaData, idx[i], 100, GR_order ); + } + + return; +} + + +static int16_t try_differential( + const int16_t numCodingBands, + const float *masa_to_total_energy_ratio, + int16_t ratio_ism_idx[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS], + const int16_t nchan_ism, + const int16_t bits_index, + int16_t *p_b_signif ) +{ + int16_t b, i; + int16_t nbits0; + int16_t b_signif; + int16_t ratio_ism_idx_ref[MAX_NUM_OBJECTS]; + int16_t diff_idx[MAX_NUM_OBJECTS]; + + b_signif = 0; + while ( ( b_signif < numCodingBands ) && ( masa_to_total_energy_ratio[b_signif] >= MASA2TOTAL_THR ) ) + { + b_signif++; + } + + nbits0 = 0; + + if ( b_signif < numCodingBands ) + { + nbits0 = bits_index; + mvs2s( ratio_ism_idx[b_signif], ratio_ism_idx_ref, nchan_ism ); + + for ( b = b_signif + 1; b < numCodingBands; b++ ) + { + if ( masa_to_total_energy_ratio[b] < MASA2TOTAL_THR ) + { + v_sub_s( ratio_ism_idx[b], ratio_ism_idx_ref, diff_idx, nchan_ism ); + mvs2s( ratio_ism_idx[b], ratio_ism_idx_ref, nchan_ism ); + + /* transform difference index into positive */ + transform_difference_index( diff_idx, diff_idx, nchan_ism - 1 ); + + /* GR encoding */ + for ( i = 0; i < nchan_ism - 1; i++ ) + { + nbits0 += ivas_qmetadata_encode_extended_gr_length( diff_idx[i], 100, 0 ); + } + } + } + } + *p_b_signif = b_signif; + + return nbits0; +} + + +static void differential_coding_first_subframe( + BSTR_ENC_HANDLE hMetaData, + const float *masa_to_total_energy_ratio, + const int16_t b_signif, + int16_t ratio_ism_idx[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS], + const int16_t nchan_ism, + const int16_t numCodingBands, + const int16_t bits_index ) +{ + int16_t index, b; + int16_t ratio_ism_idx_ref[MAX_NUM_OBJECTS]; + int16_t diff_idx[MAX_NUM_OBJECTS]; + + /* differential encoding*/ + push_next_indice( hMetaData, 0, 1 ); + + if ( b_signif < numCodingBands ) + { + index = index_slice_enum( ratio_ism_idx[b_signif], nchan_ism ); + push_next_indice( hMetaData, index, bits_index ); + + mvs2s( ratio_ism_idx[b_signif], ratio_ism_idx_ref, nchan_ism ); + + for ( b = b_signif + 1; b < numCodingBands; b++ ) + { + if ( masa_to_total_energy_ratio[b] < MASA2TOTAL_THR ) + { + v_sub_s( ratio_ism_idx[b], ratio_ism_idx_ref, diff_idx, nchan_ism ); + mvs2s( ratio_ism_idx[b], ratio_ism_idx_ref, nchan_ism ); + + /* transform difference index into positive */ + transform_index_and_GR_encode( diff_idx, nchan_ism - 1, 0, hMetaData ); + } + } + } + + return; +} + + +static void independent_coding_ratio_ism_idx( + int16_t ratio_ism_idx[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS], /* i : ISM ratios */ + const float *masa_to_total_energy_ratio, /* i : MASA to total ratios */ + const int16_t nchan_ism, /* i : number of objects */ + const int16_t numCodingBands, /* i : number of subbands */ + const int16_t bits_index, /* i : number of bits per index */ + BSTR_ENC_HANDLE hMetaData /* i/o: metadata bitstream handle */ +) +{ + int16_t b, index; + + for ( b = 0; b < numCodingBands; b++ ) + { + if ( masa_to_total_energy_ratio[b] < MASA2TOTAL_THR ) + { + index = index_slice_enum( ratio_ism_idx[b], nchan_ism ); + push_next_indice( hMetaData, index, bits_index ); + } + } + + return; +} + + +static void remove_sep_obj( + int16_t *diff_idx, /* i/o: array of difference of indexes */ + const int16_t nchan_ism, /* i : number of objects */ + const int16_t idx_sep_obj /* i : index of separated object, to be taken out of array */ +) +{ + int16_t i; + + for ( i = idx_sep_obj; i < nchan_ism - 1; i++ ) + { + diff_idx[i] = diff_idx[i + 1]; + } + + return; +} + + +static void estimate_bits_subband_ism_ratio( + const int16_t *ratio_ism_idx, + const int16_t *ratio_ism_idx_ref, /* ( i/o ) */ + const int16_t nchan_ism, + const int16_t shift_one, + const int16_t idx_sep_obj, + int16_t *p_nbits0, + int16_t *p_nbits1 ) +{ + int16_t diff_idx[MAX_NUM_OBJECTS]; + int16_t nbits0, nbits1; + int16_t i; + + nbits0 = 0; + nbits1 = 0; + + /* take difference with respect to previous subframe */ + v_sub_s( ratio_ism_idx, ratio_ism_idx_ref, diff_idx, nchan_ism ); + + if ( shift_one ) + { + remove_sep_obj( diff_idx, nchan_ism, idx_sep_obj ); + } + + /* transform difference index into positive */ + transform_difference_index( diff_idx, diff_idx, nchan_ism - 1 - shift_one ); + + /* GR encoding */ + for ( i = 0; i < nchan_ism - 1 - shift_one; i++ ) + { + nbits0 += ivas_qmetadata_encode_extended_gr_length( diff_idx[i], 100, 0 ); + nbits1 += ivas_qmetadata_encode_extended_gr_length( diff_idx[i], 100, 1 ); + } + + *p_nbits0 = nbits0; + *p_nbits1 = nbits1; + + return; +} + + +static int16_t encode_ratio_ism_subframe( + int16_t ratio_ism_idx[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS], + const int16_t nchan_ism, + const uint8_t numCodingBands, + const int16_t sf, + int16_t ratio_ism_idx_prev_sf[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS], + BSTR_ENC_HANDLE hMetaData, + const float *masa_to_total_energy_ratio, + const int16_t shift_one, + const int16_t idx_separated_obj ) +{ + int16_t b, b_signif; + int16_t diff_idx[MAX_NUM_OBJECTS]; + int16_t nbits, nbits0, nbits1, GR_order, GR_order_sb, bits_pos0; + int16_t differential_subframe; + int16_t ratio_ism_idx_ref[MAX_NUM_OBJECTS]; + int16_t bits_index; + int16_t nbits00, nbits11; + int16_t idx_sep_obj_local; + + idx_sep_obj_local = idx_separated_obj; + if ( idx_separated_obj > -1 ) + { + if ( idx_separated_obj == nchan_ism - 1 ) + { + idx_sep_obj_local = 0; + } + } + nbits = 0; + nbits0 = 0; + nbits1 = 0; + + bits_pos0 = hMetaData->nb_bits_tot; + differential_subframe = 1; /* the differences are taken with respect to previous subframe */ + + /* first subframe */ + bits_index = 0; + if ( sf == 0 ) + { + bits_index = bits_index_ism_ratio( nchan_ism ); + + nbits = 0; + for ( b = 0; b < numCodingBands; b++ ) + { + if ( masa_to_total_energy_ratio[b] < MASA2TOTAL_THR ) + { + nbits += bits_index; + } + } + + nbits0 = try_differential( numCodingBands, masa_to_total_energy_ratio, ratio_ism_idx, nchan_ism, bits_index, &b_signif ); + + if ( nbits <= nbits0 && nbits > 0 ) + { + /* independent encoding */ + push_next_indice( hMetaData, 1, 1 ); + independent_coding_ratio_ism_idx( ratio_ism_idx, masa_to_total_energy_ratio, nchan_ism, numCodingBands, bits_index, hMetaData ); + nbits = nbits + 1; + } + else + { + if ( nbits > 0 ) + { + differential_coding_first_subframe( hMetaData, masa_to_total_energy_ratio, b_signif, ratio_ism_idx, nchan_ism, numCodingBands, bits_index ); + nbits = nbits0 + 1; + } + } + +#ifdef DEBUGGING + assert( nbits == ( hMetaData->nb_bits_tot - bits_pos0 ) ); +#endif + } + else + { + /* not first subframe */ + if ( shift_one == 1 && nchan_ism == 2 ) + { + nbits = 0; + } + else + { + nbits0 = 0; + nbits1 = 0; + + for ( b = 0; b < numCodingBands; b++ ) + { + if ( masa_to_total_energy_ratio[b] < MASA2TOTAL_THR ) + { + estimate_bits_subband_ism_ratio( ratio_ism_idx[b], ratio_ism_idx_prev_sf[b], nchan_ism, shift_one, idx_sep_obj_local, &nbits00, &nbits11 ); + nbits0 += nbits00; + nbits1 += nbits11; + } + } + if ( nbits0 < nbits1 ) + { + GR_order = 0; + nbits = nbits0; + } + else + { + GR_order = 1; + nbits = nbits1; + } + + if ( numCodingBands > 1 ) + { + /* try the difference from subband to subband; first subband is compared to previous subframe first subband*/ + /* take difference with respect to previous subframe only for first subband */ + nbits0 = 0; + nbits1 = 0; + b_signif = 0; + while ( ( b_signif < numCodingBands ) && ( masa_to_total_energy_ratio[b_signif] >= MASA2TOTAL_THR ) ) + { + b_signif++; + } + + if ( b_signif < numCodingBands ) + { + estimate_bits_subband_ism_ratio( ratio_ism_idx[b_signif], ratio_ism_idx_prev_sf[b_signif], nchan_ism, shift_one, idx_sep_obj_local, &nbits0, &nbits1 ); + + mvs2s( ratio_ism_idx[b_signif], ratio_ism_idx_ref, nchan_ism ); + + for ( b = b_signif + 1; b < numCodingBands; b++ ) + { + if ( masa_to_total_energy_ratio[b] < MASA2TOTAL_THR ) + { + estimate_bits_subband_ism_ratio( ratio_ism_idx[b], ratio_ism_idx_ref, nchan_ism, shift_one, idx_sep_obj_local, &nbits00, &nbits11 ); + nbits0 += nbits00; + nbits1 += nbits11; + mvs2s( ratio_ism_idx[b], ratio_ism_idx_ref, nchan_ism ); + } + } + + if ( nbits0 < nbits1 ) + { + GR_order_sb = 0; + } + else + { + GR_order_sb = 1; + nbits0 = nbits1; + } + + if ( nbits0 < nbits ) + { + differential_subframe = 0; + nbits = nbits0; + GR_order = GR_order_sb; + } + + if ( nbits > 0 ) + { + /* write prediction type */ + push_next_indice( hMetaData, differential_subframe, 1 ); + /* write GR order */ + push_next_indice( hMetaData, GR_order, 1 ); + nbits++; /* for the prediction type */ + nbits++; /* for GR_order */ + + /* write data */ + if ( differential_subframe ) + { + for ( b = 0; b < numCodingBands; b++ ) + { + if ( masa_to_total_energy_ratio[b] < MASA2TOTAL_THR ) + { + /* take difference with respect to previous subframe */ + v_sub_s( ratio_ism_idx[b], ratio_ism_idx_prev_sf[b], diff_idx, nchan_ism ); + + if ( shift_one ) + { + remove_sep_obj( diff_idx, nchan_ism, idx_sep_obj_local ); + } + + transform_index_and_GR_encode( diff_idx, nchan_ism - 1 - shift_one, GR_order, hMetaData ); + } + } + } + else + { + v_sub_s( ratio_ism_idx[b_signif], ratio_ism_idx_prev_sf[b_signif], diff_idx, nchan_ism ); + + if ( shift_one ) + { + remove_sep_obj( diff_idx, nchan_ism, idx_sep_obj_local ); + } + + transform_index_and_GR_encode( diff_idx, nchan_ism - 1 - shift_one, GR_order, hMetaData ); + + mvs2s( ratio_ism_idx[b_signif], ratio_ism_idx_ref, nchan_ism - shift_one ); + + for ( b = b_signif + 1; b < numCodingBands; b++ ) + { + /* take difference with respect to previous subband */ + if ( masa_to_total_energy_ratio[b] < MASA2TOTAL_THR ) + { + v_sub_s( ratio_ism_idx[b], ratio_ism_idx_ref, diff_idx, nchan_ism ); + + if ( shift_one ) + { + remove_sep_obj( diff_idx, nchan_ism, idx_sep_obj_local ); + } + + transform_index_and_GR_encode( diff_idx, nchan_ism - 1 - shift_one, GR_order, hMetaData ); + + mvs2s( ratio_ism_idx[b], ratio_ism_idx_ref, nchan_ism - shift_one ); + } + } + } + } + } + } + else + { + /* only differential wrt previous subframe is possible */ + /* write the differential to subframe case and no bit to signal the difference type */ + + if ( nbits > 0 ) + { + /* write GR order */ + push_next_indice( hMetaData, GR_order, 1 ); + nbits++; /* for GR_order */ + /* write data */ + /* only one subband */ + if ( masa_to_total_energy_ratio[0] < MASA2TOTAL_THR ) + { + /* take difference with respect to previous subframe */ + v_sub_s( ratio_ism_idx[0], ratio_ism_idx_prev_sf[0], diff_idx, nchan_ism ); + + if ( shift_one ) + { + remove_sep_obj( diff_idx, nchan_ism, idx_sep_obj_local ); + } + + transform_index_and_GR_encode( diff_idx, nchan_ism - 1 - shift_one, GR_order, hMetaData ); + } + } + } + +#ifdef DEBUGGING + assert( nbits == ( hMetaData->nb_bits_tot - bits_pos0 ) ); +#endif + } + } + + return nbits; +} + + +static void ivas_encode_masaism_metadata( + MASA_ENCODER_HANDLE hMasa, + IVAS_QMETADATA_HANDLE hQMetaData, /* i/o: q_metadata handle */ + BSTR_ENC_HANDLE hMetaData, /* i/o: metadata bitstream handle */ + ISM_METADATA_HANDLE hIsmMeta[], /* i/o: ISM metadata handles */ + const int16_t low_bitrate_mode, /* i : is low bitrate more? 1/0 */ + const int16_t omasa_nbands, + const int16_t omasa_nblocks, + const int16_t idx_separated_object, + const int16_t ism_imp ) +{ + int16_t sf, band; + uint8_t numCodingBands; + uint8_t numSf; + int16_t brange[2]; + float eneBand; + int16_t bin; + int16_t obj; + int16_t bits_ism[MAX_NUM_OBJECTS]; + uint16_t idx_sph; + float theta_q, phi_q; + uint16_t index_theta, index_phi; + float ratio_ism[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS]; + int16_t ratio_ism_idx[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS], ratio_ism_idx_prev_sf[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS]; + float step; + int16_t inv_step; + float energy_ism, energy_ism_ind[MAX_NUM_OBJECTS]; + int16_t tmp, rotate; + int16_t n_ism_tmp, i; + + + /* use the values from hQMetaData */ + numCodingBands = (uint8_t) hQMetaData->q_direction->cfg.nbands; + numSf = (int8_t) hQMetaData->q_direction->cfg.nblocks; + + if ( numCodingBands != omasa_nbands ) + { + assert( numCodingBands == 1 ); + + for ( sf = 0; sf < numSf; sf++ ) + { + if ( sum_f( hMasa->data.energy_ism[sf], omasa_nbands ) == 0.0f ) + { + hQMetaData->masa_to_total_energy_ratio[sf][0] = 1.0f; + } + else + { + brange[0] = hMasa->data.band_mapping[0]; + brange[1] = hMasa->data.band_mapping[omasa_nbands]; + eneBand = 0.0f; + for ( bin = brange[0]; bin < brange[1]; bin++ ) + { + eneBand += hMasa->data.energy[sf][bin]; + } + + energy_ism = 0.0f; + for ( obj = 0; obj < hMasa->data.nchan_ism; obj++ ) + { + energy_ism_ind[obj] = 0.0f; + } + + for ( band = 0; band < omasa_nbands; band++ ) + { + energy_ism += hMasa->data.energy_ism[sf][band]; + for ( obj = 0; obj < hMasa->data.nchan_ism; obj++ ) + { + energy_ism_ind[obj] += hMasa->data.energy_ism[sf][band] * hMasa->data.energy_ratio_ism[sf][band][obj]; + } + } + + for ( obj = 0; obj < hMasa->data.nchan_ism; obj++ ) + { + hMasa->data.energy_ratio_ism[sf][0][obj] = energy_ism_ind[obj] / energy_ism; + } + hQMetaData->masa_to_total_energy_ratio[sf][0] = eneBand / ( eneBand + energy_ism + EPSILON ); + } + } + } + else if ( numSf != omasa_nblocks ) + { + assert( numSf == 1 ); + + for ( band = 0; band < numCodingBands; band++ ) + { + energy_ism = 0.0f; /* ISM energy for current subband */ + for ( obj = 0; obj < hMasa->data.nchan_ism; obj++ ) + { + energy_ism_ind[obj] = 0.0f; + } + for ( sf = 0; sf < omasa_nblocks; sf++ ) + { + energy_ism += hMasa->data.energy_ism[sf][band]; + for ( obj = 0; obj < hMasa->data.nchan_ism; obj++ ) + { + energy_ism_ind[obj] += hMasa->data.energy_ism[sf][band] * hMasa->data.energy_ratio_ism[sf][band][obj]; + } + } + + if ( energy_ism == 0.0f ) + { + hQMetaData->masa_to_total_energy_ratio[0][band] = 1.0f; + } + else + { + for ( obj = 0; obj < hMasa->data.nchan_ism; obj++ ) + { + hMasa->data.energy_ratio_ism[0][band][obj] = energy_ism_ind[obj] / energy_ism; + } + brange[0] = hMasa->data.band_mapping[band]; + brange[1] = hMasa->data.band_mapping[band + 1]; + + eneBand = 0.0f; + for ( sf = 0; sf < omasa_nblocks; sf++ ) + { + for ( bin = brange[0]; bin < brange[1]; bin++ ) + { + eneBand += hMasa->data.energy[sf][bin]; + } + } + hQMetaData->masa_to_total_energy_ratio[0][band] = eneBand / ( eneBand + energy_ism + EPSILON ); + } + } + } + else + { + for ( sf = 0; sf < numSf; sf++ ) + { + for ( band = 0; band < numCodingBands; band++ ) + { + if ( hMasa->data.energy_ism[sf][band] == 0.0f ) + { + hQMetaData->masa_to_total_energy_ratio[sf][band] = 1.0f; + } + else + { + brange[0] = hMasa->data.band_mapping[band]; + brange[1] = hMasa->data.band_mapping[band + 1]; + + eneBand = 0.0f; + for ( bin = brange[0]; bin < brange[1]; bin++ ) + { + eneBand += hMasa->data.energy[sf][bin]; + } + hQMetaData->masa_to_total_energy_ratio[sf][band] = eneBand / ( eneBand + hMasa->data.energy_ism[sf][band] + EPSILON ); + } + } + } + } + + encode_masa_to_total( hQMetaData, hMetaData, low_bitrate_mode, numCodingBands, numSf ); + + /* quantize ism_ratios */ + if ( hMasa->data.nchan_ism > 1 ) + { + inv_step = ( ( 1 << PARAM_ISM_POW_RATIO_NBITS ) - 1 ); + step = 1.0f / inv_step; + + rotate = 0; + n_ism_tmp = 0; + + for ( sf = 0; sf < numSf; sf++ ) + { + for ( band = 0; band < numCodingBands; band++ ) + { + for ( obj = 0; obj < hMasa->data.nchan_ism; obj++ ) + { + assert( ( hMasa->data.energy_ratio_ism[sf][band][obj] >= 0 ) && ( hMasa->data.energy_ratio_ism[sf][band][obj] <= 1 ) ); + ratio_ism[band][obj] = hMasa->data.energy_ratio_ism[sf][band][obj]; + } + + /* Quantize ISM ratios */ + quantize_ratio_ism_vector( ratio_ism[band], ratio_ism_idx[band], hMasa->data.nchan_ism, hQMetaData->masa_to_total_energy_ratio[sf][band], idx_separated_object ); + + if ( n_ism_tmp == numCodingBands && ratio_ism_idx[band][idx_separated_object] != 0 && hQMetaData->masa_to_total_energy_ratio[sf][band] < MASA2TOTAL_THR ) + { + i = 0; + while ( ratio_ism_idx[band][idx_separated_object] > 0 ) + { + if ( i != idx_separated_object ) + { + ratio_ism_idx[band][i]++; + ratio_ism_idx[band][idx_separated_object]--; + } + i++; + if ( i == hMasa->data.nchan_ism ) + { + i = 0; + } + } + } + + /* reconstructed values */ + reconstruct_ism_ratios( ratio_ism_idx[band], hMasa->data.nchan_ism, step, hMasa->data.q_energy_ratio_ism[sf][band] ); + /* encode vector */ + } + + if ( ( hMasa->data.nchan_ism > 2 ) && ( idx_separated_object == hMasa->data.nchan_ism - 1 ) ) + { + /* rotate components */ + rotate = 1; + for ( band = 0; band < numCodingBands; band++ ) + { + if ( hQMetaData->masa_to_total_energy_ratio[sf][band] < MASA2TOTAL_THR ) + { + tmp = ratio_ism_idx[band][hMasa->data.nchan_ism - 1]; + ratio_ism_idx[band][hMasa->data.nchan_ism - 1] = ratio_ism_idx[band][0]; + ratio_ism_idx[band][0] = tmp; + if ( sf == 0 && tmp == 0 ) + { + n_ism_tmp += 1; + } + + if ( n_ism_tmp == numCodingBands ) + { + assert( tmp == 0 ); + } + } + } + } + else + { + if ( idx_separated_object > -1 ) + { + for ( band = 0; band < numCodingBands; band++ ) + { + if ( hQMetaData->masa_to_total_energy_ratio[sf][band] < MASA2TOTAL_THR ) + { + if ( ratio_ism_idx[band][idx_separated_object] == 0 && sf == 0 ) + { + n_ism_tmp++; + } + } + } + } + } + + /* encode data for current subframe */ + if ( sf > 0 && n_ism_tmp == numCodingBands ) + { + encode_ratio_ism_subframe( ratio_ism_idx, hMasa->data.nchan_ism, numCodingBands, sf, ratio_ism_idx_prev_sf, hMetaData, hQMetaData->masa_to_total_energy_ratio[sf], 1, idx_separated_object ); + } + else + { + encode_ratio_ism_subframe( ratio_ism_idx, hMasa->data.nchan_ism, numCodingBands, sf, ratio_ism_idx_prev_sf, hMetaData, hQMetaData->masa_to_total_energy_ratio[sf], 0, idx_separated_object ); + } + + /* calculate quantized ISM ratios */ + /* save previous subframe indexes */ + for ( band = 0; band < numCodingBands; band++ ) + { + mvs2s( ratio_ism_idx[band], ratio_ism_idx_prev_sf[band], hMasa->data.nchan_ism ); + } + + if ( rotate ) + { + for ( band = 0; band < numCodingBands; band++ ) + { + if ( hQMetaData->masa_to_total_energy_ratio[sf][band] < MASA2TOTAL_THR ) + { + tmp = ratio_ism_idx[band][hMasa->data.nchan_ism - 1]; + ratio_ism_idx[band][hMasa->data.nchan_ism - 1] = ratio_ism_idx[band][0]; + ratio_ism_idx[band][0] = tmp; + } + } + } + } + } + + calculate_nbits_meta( hMasa->data.nchan_ism, hMasa->data.q_energy_ratio_ism, hQMetaData->masa_to_total_energy_ratio, numSf, numCodingBands, bits_ism, idx_separated_object, ism_imp ); + + /* quantize directions */ + for ( obj = 0; obj < hMasa->data.nchan_ism; obj++ ) + { + if ( bits_ism[obj] < 8 ) + { + /* check is same as previous */ + if ( ( fabs( hIsmMeta[obj]->elevation - hIsmMeta[obj]->q_elevation_old ) < 0.01f ) && ( fabs( hIsmMeta[obj]->azimuth - hIsmMeta[obj]->q_azimuth_old ) < 0.01f ) ) + { + push_next_indice( hMetaData, 1, 1 ); + /* the old stays the same */ + } + else + { + push_next_indice( hMetaData, 0, 1 ); + idx_sph = quantize_direction( hIsmMeta[obj]->elevation, hIsmMeta[obj]->azimuth, bits_ism[obj], &theta_q, &phi_q, &index_theta, &index_phi, MC_LS_SETUP_INVALID ); + push_next_indice( hMetaData, idx_sph, bits_ism[obj] ); + hIsmMeta[obj]->q_elevation_old = hIsmMeta[obj]->elevation; + hIsmMeta[obj]->q_azimuth_old = hIsmMeta[obj]->azimuth; + } + } + else + { + idx_sph = quantize_direction( hIsmMeta[obj]->elevation, hIsmMeta[obj]->azimuth, bits_ism[obj], &theta_q, &phi_q, &index_theta, &index_phi, MC_LS_SETUP_INVALID ); + push_next_indice( hMetaData, idx_sph, bits_ism[obj] ); + hIsmMeta[obj]->q_elevation_old = hIsmMeta[obj]->elevation; + hIsmMeta[obj]->q_azimuth_old = hIsmMeta[obj]->azimuth; + } + } + + return; +} + + +/*-------------------------------------------------------------------* + * ivas_merge_masa_transports() + * + * Merge MASA transport channels + *-------------------------------------------------------------------*/ + +void ivas_merge_masa_transports( + float data_in_f1[][L_FRAME48k], + float data_in_f2[][L_FRAME48k], + float data_out_f[][L_FRAME48k], + const int16_t input_frame, + const int16_t num_transport_channels ) +{ + int16_t i, j; + + for ( i = 0; i < num_transport_channels; i++ ) + { + for ( j = 0; j < input_frame; j++ ) + { + data_out_f[i][j] = data_in_f1[i][j] + data_in_f2[i][j]; + } + } + + return; +} +#endif diff --git a/lib_enc/ivas_mc_param_enc.c b/lib_enc/ivas_mc_param_enc.c index 2979a9bdb5621ab83df96f06ec98553b9d99269d..fe4f8e8cfcc54912cb246b4f5eb1ea9f0735537f 100644 --- a/lib_enc/ivas_mc_param_enc.c +++ b/lib_enc/ivas_mc_param_enc.c @@ -35,7 +35,9 @@ #include "options.h" #include "cnst.h" #include "rom_enc.h" +#ifdef FIX_580_PARAMMC_ENER_BURSTS #include "ivas_rom_enc.h" +#endif #include "rom_com.h" #include "prot.h" #include "ivas_prot.h" @@ -213,11 +215,13 @@ ivas_error ivas_param_mc_enc_open( /* Init total/dmx ener factors */ set_f( hParamMC->ener_fac, 0.0f, PARAM_MC_MAX_PARAMETER_BANDS ); +#ifdef FIX_580_PARAMMC_ENER_BURSTS /* init previous ILDs */ for ( i = 0; i < PARAM_MC_MAX_PARAMETER_BANDS; i++ ) { set_zero( hParamMC->prev_ilds[i], PARAM_MC_SZ_ILD_MAP ); } +#endif st_ivas->hParamMC = hParamMC; @@ -489,6 +493,10 @@ void ivas_param_mc_enc( { hParamMC->hMetadataPMC.attackIndex = 0; } + +#ifndef FIX_580_PARAMMC_ENER_BURSTS + band_step = hParamMC->hMetadataPMC.bAttackPresent ? PARAM_MC_TRANSIENT_BAND_STEP : 1; +#endif } break; #ifdef DEBUGGING @@ -501,7 +509,9 @@ void ivas_param_mc_enc( /* parameter estimation*/ ivas_param_mc_param_est_enc( hParamMC, data_f, Cy_sum, Cx_sum, input_frame, nchan_inp, st_ivas->nchan_transport ); +#ifdef FIX_580_PARAMMC_ENER_BURSTS band_step = hParamMC->hMetadataPMC.bAttackPresent ? PARAM_MC_TRANSIENT_BAND_STEP : 1; +#endif /* ILD parameter quantization */ @@ -837,6 +847,7 @@ static void ivas_param_mc_param_est_enc( } } +#ifdef FIX_580_PARAMMC_ENER_BURSTS if ( !hParamMC->hMetadataPMC.bAttackPresent ) { const PARAM_MC_ILD_MAPPING *h_ild_mapping; @@ -892,6 +903,7 @@ static void ivas_param_mc_param_est_enc( hParamMC->hMetadataPMC.bAttackPresent = 1; } } +#endif if ( hParamMC->hMetadataPMC.bAttackPresent ) @@ -920,7 +932,11 @@ static void ivas_param_mc_param_est_enc( for ( ; cur_param_band < num_parameter_bands; cur_param_band += 2 ) { +#ifdef FIX_563_PARAMMC_LIMITER if ( cur_param_band < num_parameter_bands ) +#else + if ( cur_param_band + 1 < num_parameter_bands ) +#endif { for ( ch_idx1 = 0; ch_idx1 < nchan_transport; ++ch_idx1 ) { @@ -1316,7 +1332,11 @@ static void ivas_param_mc_quantize_ilds( ener_fac = 10.0f * log10f( ( tot_ener + EPSILON ) / ( dmx_ener + EPSILON ) ); delta_fac = ener_fac - hParamMC->ener_fac[freq_idx]; +#ifdef FIX_563_PARAMMC_LIMITER if ( !hParamMC->hMetadataPMC.bAttackPresent && ( delta_fac > PARAM_MC_ENER_LIMIT_INTERFRAME ) && ( delta_fac < PARAM_MC_ENER_LIMIT_MAX_DELTA_FAC ) ) +#else + if ( !hParamMC->hMetadataPMC.bAttackPresent && ( delta_fac > PARAM_MC_ENER_LIMIT_INTERFRAME ) ) +#endif { float limit_fac; limit_fac = powf( 10.0f, ( ( 0.3f * logf( delta_fac - PARAM_MC_ENER_LIMIT_INTERFRAME + 1.0f ) - ( delta_fac - PARAM_MC_ENER_LIMIT_INTERFRAME ) ) / 10.0f ) ); @@ -1326,11 +1346,13 @@ static void ivas_param_mc_quantize_ilds( hParamMC->ener_fac[freq_idx] = ener_fac; +#ifdef FIX_563_PARAMMC_LIMITER /* update also combined bands ener_fac when in transient frame */ if ( hParamMC->hMetadataPMC.bAttackPresent && ( ( freq_idx + 1 ) < hParamMC->hMetadataPMC.nbands_coded ) ) { hParamMC->ener_fac[freq_idx + 1] = ener_fac; } +#endif for ( k = 0; k < num_ilds_to_code; ++k ) { @@ -1344,11 +1366,13 @@ static void ivas_param_mc_quantize_ilds( ref_ener += Cx[ref_channel_idx][ref_channel_idx]; } ILD[k] = 10.0f * log10f( ( Nrg[h_ild_mapping->ild_index[k]] + EPSILON ) / ( hParamMC->hMetadataPMC.ild_factors[k] * ref_ener + EPSILON ) ); +#ifdef FIX_580_PARAMMC_ENER_BURSTS hParamMC->prev_ilds[freq_idx][k] = ILD[k]; if ( hParamMC->hMetadataPMC.bAttackPresent && ( ( freq_idx + 1 ) < hParamMC->hMetadataPMC.nbands_coded ) ) { hParamMC->prev_ilds[freq_idx + 1][k] = ILD[k]; } +#endif } @@ -1720,6 +1744,7 @@ static void ivas_param_mc_encode_parameter( if ( hMetadataPMC->bAttackPresent || hMetadataPMC->param_frame_idx == hMetadataPMC->coding_band_mapping[i] ) { /* LFE ICC/ILDs are always the last ones in coding band 0 */ +#ifdef FIX_578_PARAMMC_ILD_BS int16_t n_lfe_idx, k; n_lfe_idx = map_size - map_size_wo_lfe; for ( k = 0; k < n_lfe_idx; k++ ) @@ -1730,6 +1755,13 @@ static void ivas_param_mc_encode_parameter( idx_prev = idx; sz_seq++; } +#else + idx = quant_idx[( i + 1 ) * map_size - 1]; + seq[sz_seq] = idx; + seq_delta[sz_seq] = idx - idx_prev + idx_offset; + idx_prev = idx; + sz_seq++; +#endif } } } diff --git a/lib_enc/ivas_omasa_enc.c b/lib_enc/ivas_omasa_enc.c new file mode 100644 index 0000000000000000000000000000000000000000..aaa4627361c7a006a20bfd648292aa352807f38c --- /dev/null +++ b/lib_enc/ivas_omasa_enc.c @@ -0,0 +1,1170 @@ +/****************************************************************************************************** + + (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +#include "options.h" +#include +#include +#include +#include "ivas_cnst.h" +#include "ivas_prot.h" +#include "prot.h" +#include "ivas_rom_com.h" +#include "ivas_rom_enc.h" +#ifdef DEBUGGING +#include "debug.h" +#endif +#include "wmc_auto.h" + +#ifdef MASA_AND_OBJECTS + +/*------------------------------------------------------------------------- + * Local function prototypes + *------------------------------------------------------------------------*/ + +static void ivas_omasa_param_est_enc( OMASA_ENC_HANDLE hOMasa, MASA_ENCODER_HANDLE hMasa, ISM_METADATA_HANDLE hIsmMeta[], float data_f[][L_FRAME48k], float elevation_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], float azimuth_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], float energyRatio[MASA_FREQUENCY_BANDS], float spreadCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], float surroundingCoherence[MASA_FREQUENCY_BANDS], float diffuseness_m[MASA_FREQUENCY_BANDS], const int16_t input_frame, const int16_t nchan_inp ); + +static void ivas_omasa_energy_and_ratio_est( OMASA_ENC_HANDLE hOMasa, MASA_ENCODER_HANDLE hMasa, float data_f[][L_FRAME48k], const int16_t input_frame, const int16_t nchan_inp ); + +static void ivas_omasa_dmx( float data_in_f[][L_FRAME48k], float data_out_f[][L_FRAME48k], const int16_t input_frame, const int16_t nchan_transport, const int16_t nchan_ism, ISM_METADATA_HANDLE hIsmMeta[], float prev_gains[][MASA_MAX_TRANSPORT_CHANNELS], const float interpolator[L_FRAME48k] ); + +static void computeIntensityVector_enc( const int16_t *band_grouping, float Cldfb_RealBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX], float Cldfb_ImagBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX], const int16_t num_frequency_bands, float intensity_real[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS] ); + +static void computeReferencePower_omasa( const int16_t *band_grouping, float Cldfb_RealBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX], float Cldfb_ImagBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX], float *reference_power, const int16_t enc_param_start_band, const int16_t num_freq_bands ); + +/*--------------------------------------------------------------------------* + * ivas_omasa_enc_open() + * + * Allocate and initialize OMASA handle + *--------------------------------------------------------------------------*/ + +ivas_error ivas_omasa_enc_open( + Encoder_Struct *st_ivas /* i/o: IVAS encoder handle */ +) +{ + int16_t i, j; + OMASA_ENC_HANDLE hOMasa; + int16_t numAnalysisChannels; + int16_t input_frame; + ivas_error error; + + error = IVAS_ERR_OK; + + assert( st_ivas->hMasa != NULL && "MASA encoder handle is not present" ); + + if ( ( hOMasa = (OMASA_ENC_HANDLE) malloc( sizeof( OMASA_ENC_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for OMASA encoder\n" ) ); + } + + numAnalysisChannels = st_ivas->hEncoderConfig->nchan_ism; + + /* open/initialize CLDFB */ + hOMasa->num_Cldfb_instances = numAnalysisChannels; + for ( i = 0; i < hOMasa->num_Cldfb_instances; i++ ) + { + openCldfb( &( hOMasa->cldfbAnaEnc[i] ), CLDFB_ANALYSIS, st_ivas->hEncoderConfig->input_Fs, CLDFB_PROTOTYPE_5_00MS ); + } + + /* intensity 3-dim */ + for ( i = 0; i < DIRAC_NUM_DIMS; i++ ) + { + hOMasa->direction_vector_m[i] = (float **) malloc( MAX_PARAM_SPATIAL_SUBFRAMES * sizeof( float * ) ); + + for ( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ ) + { + hOMasa->direction_vector_m[i][j] = (float *) malloc( MASA_FREQUENCY_BANDS * sizeof( float ) ); + set_zero( hOMasa->direction_vector_m[i][j], MASA_FREQUENCY_BANDS ); + } + } + + for ( i = 0; i < DIRAC_NUM_DIMS; i++ ) + { + for ( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ ) + { + hOMasa->buffer_intensity_real[i][j] = (float *) malloc( MASA_FREQUENCY_BANDS * sizeof( float ) ); + set_zero( hOMasa->buffer_intensity_real[i][j], MASA_FREQUENCY_BANDS ); + } + } + + set_zero( hOMasa->buffer_energy, DIRAC_NO_COL_AVG_DIFF * MASA_FREQUENCY_BANDS ); + + for ( i = 0; i < MAX_NUM_OBJECTS; i++ ) + { + set_f( hOMasa->prev_object_dm_gains[i], (float) sqrt( 0.5 ), MASA_MAX_TRANSPORT_CHANNELS ); + } + set_zero( hOMasa->broadband_energy_sm, MAX_NUM_OBJECTS + MASA_MAX_TRANSPORT_CHANNELS ); + set_zero( hOMasa->broadband_energy_prev, MAX_NUM_OBJECTS + MASA_MAX_TRANSPORT_CHANNELS ); + hOMasa->prev_selected_object = 0; + hOMasa->changing_object = 0; + + input_frame = (int16_t) ( st_ivas->hEncoderConfig->input_Fs / FRAMES_PER_SEC ); + for ( i = 0; i < input_frame; i++ ) + { + hOMasa->interpolator[i] = ( (float) i ) / ( (float) input_frame ); + hOMasa->fade_out_gain[i] = ( 1.0f + cosf( ( (float) i ) / ( (float) input_frame ) * EVS_PI ) ) / 2.0f; + hOMasa->fade_in_gain[i] = 1.0f - hOMasa->fade_out_gain[i]; + } + + hOMasa->index_buffer_intensity = 0; + + st_ivas->hOMasa = hOMasa; + + return error; +} + + +/*--------------------------------------------------------------------------* + * ivas_omasa_enc_close() + * + * Close OMASA handle + *--------------------------------------------------------------------------*/ + +void ivas_omasa_enc_close( + OMASA_ENC_HANDLE *hOMasa /* i/o: encoder OMASA handle */ +) +{ + int16_t i, j; + + if ( hOMasa == NULL || *hOMasa == NULL ) + { + return; + } + + for ( i = 0; i < ( *hOMasa )->num_Cldfb_instances; i++ ) + { + deleteCldfb( &( ( *hOMasa )->cldfbAnaEnc[i] ) ); + } + + for ( i = 0; i < DIRAC_NUM_DIMS; i++ ) + { + for ( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ ) + { + free( ( *hOMasa )->direction_vector_m[i][j] ); + ( *hOMasa )->direction_vector_m[i][j] = NULL; + } + + for ( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ ) + { + free( ( *hOMasa )->buffer_intensity_real[i][j] ); + ( *hOMasa )->buffer_intensity_real[i][j] = NULL; + } + + free( ( *hOMasa )->direction_vector_m[i] ); + ( *hOMasa )->direction_vector_m[i] = NULL; + } + + free( *hOMasa ); + ( *hOMasa ) = NULL; + + return; +} + + +/*--------------------------------------------------------------------------* + * ivas_omasa_enc_config() + * + * oMASA encoder configuration + *--------------------------------------------------------------------------*/ + +ivas_error ivas_omasa_enc_config( + Encoder_Struct *st_ivas /* i/o: IVAS encoder structure */ +) +{ + int16_t k, sce_id, nSCE_old; + int32_t ivas_total_brate, ism_total_brate; + ENCODER_CONFIG_HANDLE hEncoderConfig; + ivas_error error; + + hEncoderConfig = st_ivas->hEncoderConfig; + ivas_total_brate = hEncoderConfig->ivas_total_brate; + nSCE_old = st_ivas->nSCE; + + st_ivas->ism_mode = ivas_omasa_ism_mode_select( ivas_total_brate, hEncoderConfig->nchan_ism ); + st_ivas->nchan_transport = 2; + + /* reconfiguration in case of bitrate switching */ + if ( hEncoderConfig->last_ivas_total_brate != ivas_total_brate ) + { + ivas_set_omasa_TC( st_ivas->ism_mode, hEncoderConfig->nchan_ism, &st_ivas->nSCE, &st_ivas->nCPE ); + + k = 0; + while ( k < SIZE_IVAS_BRATE_TBL && ivas_total_brate != ivas_brate_tbl[k] ) + { + k++; + } + + ism_total_brate = 0; + for ( sce_id = 0; sce_id < st_ivas->nSCE; sce_id++ ) + { + ism_total_brate += sep_object_brate[k - 2][st_ivas->nSCE - 1]; + } + + if ( st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) + { + if ( ( error = ivas_ism_config( st_ivas->hEncoderConfig->ivas_total_brate, st_ivas->nchan_transport, 1, NULL, 0, NULL, NULL, NULL, NULL, NULL, 1 ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else if ( st_ivas->ism_mode == ISM_MASA_MODE_DISC ) + { + if ( ( error = ivas_ism_config( st_ivas->hEncoderConfig->ivas_total_brate, st_ivas->nchan_transport, st_ivas->nSCE, NULL, 0, NULL, NULL, NULL, NULL, NULL, 1 ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + /* reconfigure core-coders for ISMs */ + if ( ( error = ivas_corecoder_enc_reconfig( st_ivas, nSCE_old, 1, 2, st_ivas->nSCE > 0 ? sep_object_brate[k - 2][st_ivas->nSCE - 1] : 0, ivas_total_brate - ism_total_brate, MC_MODE_NONE ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* re-write IVAS format signalling - actual 'ism_mode' was not known before */ + if ( st_ivas->nSCE > 0 ) + { + reset_indices_enc( st_ivas->hSCE[0]->hCoreCoder[0]->hBstr, st_ivas->hSCE[0]->hCoreCoder[0]->hBstr->nb_bits_tot ); + } + else + { + reset_indices_enc( st_ivas->hCPE[0]->hCoreCoder[0]->hBstr, st_ivas->hCPE[0]->hCoreCoder[0]->hBstr->nb_bits_tot ); + } + + ivas_write_format( st_ivas ); + + if ( st_ivas->ism_mode != ISM_MASA_MODE_DISC && st_ivas->hOMasa == NULL ) + { + if ( ( error = ivas_omasa_enc_open( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else if ( st_ivas->ism_mode == ISM_MASA_MODE_DISC && st_ivas->hOMasa != NULL ) + { + ivas_omasa_enc_close( &( st_ivas->hOMasa ) ); + st_ivas->hOMasa = NULL; + } + + st_ivas->hCPE[0]->element_brate = ivas_total_brate - ism_total_brate; + + if ( ivas_total_brate - ism_total_brate >= MIN_BRATE_MDCT_STEREO ) + { + hEncoderConfig->element_mode_init = IVAS_CPE_MDCT; + } + else + { + hEncoderConfig->element_mode_init = IVAS_CPE_DFT; + } + } + + /* Configure MASA encoder based on frame parameters */ + if ( ( error = ivas_masa_enc_config( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( st_ivas->ism_mode != ISM_MASA_MODE_DISC ) + { + /* Configure oMASA analysis based on MASA config */ + ivas_omasa_set_config( st_ivas->hOMasa, st_ivas->hMasa, st_ivas->hEncoderConfig->input_Fs, st_ivas->ism_mode ); + } + + return IVAS_ERR_OK; +} + + +/*--------------------------------------------------------------------------* + * ivas_omasa_set_config() + * + * Frame-by-frame config for oMASA + *--------------------------------------------------------------------------*/ + +void ivas_omasa_set_config( + OMASA_ENC_HANDLE hOMasa, /* i/o: OMASA encoder handle */ + MASA_ENCODER_HANDLE hMasa, /* i : MASA encoder handle */ + const int32_t input_Fs, /* i : Input sample rate */ + const ISM_MODE ism_mode /* i : ISM mode */ +) +{ + uint8_t i, maxBin; + + /* Determine the number of bands */ + if ( ism_mode == ISM_MODE_NONE || ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) + { + /* use full resolution for the ISM+MASA merge and reduce later */ + hOMasa->nbands = 24; + } + else + { + hOMasa->nbands = hMasa->config.numCodingBands; + } + + hOMasa->nCodingBands = hMasa->config.numCodingBands; + + /* Determine the number of subframes */ + hOMasa->nSubframes = hMasa->config.joinedSubframes == TRUE ? 1 : MAX_PARAM_SPATIAL_SUBFRAMES; + + /* Determine band grouping */ + if ( hOMasa->nbands == 24 ) + { + mvs2s( MASA_band_grouping_24, hOMasa->band_grouping, 24 + 1 ); + } + else + { + for ( i = 0; i < hOMasa->nbands + 1; i++ ) + { + hOMasa->band_grouping[i] = MASA_band_grouping_24[hMasa->data.band_mapping[i]]; + } + } + + maxBin = (uint8_t) ( input_Fs * INV_CLDFB_BANDWIDTH + 0.5f ); + + for ( i = 1; i < hOMasa->nbands + 1; i++ ) + { + if ( hOMasa->band_grouping[i] >= maxBin ) + { + hOMasa->band_grouping[i] = maxBin; + hOMasa->nbands = i; + break; + } + } + + mvs2s( DirAC_block_grouping, hOMasa->block_grouping, MAX_PARAM_SPATIAL_SUBFRAMES + 1 ); + if ( hOMasa->nSubframes == 1 ) + { + hOMasa->block_grouping[1] = hOMasa->block_grouping[MAX_PARAM_SPATIAL_SUBFRAMES]; + } + + return; +} + + +/*--------------------------------------------------------------------------* + * ivas_omasa_enc() + * + * Main OMASA encoding function + *--------------------------------------------------------------------------*/ + +void ivas_omasa_enc( + OMASA_ENC_HANDLE hOMasa, /* i/o: OMASA encoder handle */ + MASA_ENCODER_HANDLE hMasa, /* i/o: MASA encoder handle */ + ISM_METADATA_HANDLE hIsmMeta[], /* i/o: ISM metadata handle */ + float data_in_f[][L_FRAME48k], /* i/o: Input / transport audio signals */ + const int16_t input_frame, /* i : Input frame size */ + const int16_t nchan_transport, /* i : Number of transport channels */ + const int16_t nchan_ism, /* i : Number of objects for parameter analysis */ + const ISM_MODE ism_mode, /* i : ISM mode */ + float data_separated_object[L_FRAME48k], /* o : Separated object audio signal */ + int16_t *idx_separated_object /* o : Index of the separated object */ +) +{ + int16_t i, j; + float data_out_f[MASA_MAX_TRANSPORT_CHANNELS][L_FRAME48k]; + + /* Determine separated object (when applicable) */ + if ( ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ || ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) + { + float broadband_energy[MAX_NUM_OBJECTS + MASA_MAX_TRANSPORT_CHANNELS]; + int16_t loudest_object; + int16_t selected_object; + int16_t nchan_all_inp; + float alpha; + uint8_t fade_out_separate_object; + uint8_t fade_in_separate_object; + + /* Estimate broadband energies */ + nchan_all_inp = nchan_ism + nchan_transport; + set_zero( broadband_energy, nchan_all_inp ); + for ( i = 0; i < nchan_all_inp; i++ ) + { + for ( j = 0; j < input_frame; j++ ) + { + broadband_energy[i] += data_in_f[i][j] * data_in_f[i][j]; + } + } + + /* Temporal averaging */ + alpha = 0.8f; + for ( i = 0; i < nchan_all_inp; i++ ) + { + hOMasa->broadband_energy_sm[i] = ( 1.0f - alpha ) * broadband_energy[i] + alpha * hOMasa->broadband_energy_sm[i]; + } + + /* Determine loudest object */ + loudest_object = 0; + for ( i = 1; i < nchan_ism; i++ ) + { + if ( hOMasa->broadband_energy_sm[i] > hOMasa->broadband_energy_sm[loudest_object] ) + { + loudest_object = i; + } + } + + /* Determine object to separate */ + selected_object = hOMasa->prev_selected_object; + fade_out_separate_object = 0; + fade_in_separate_object = 0; + if ( hOMasa->changing_object ) + { + hOMasa->changing_object = 0; + selected_object = loudest_object; + fade_in_separate_object = 1; + } + else + { + if ( loudest_object != hOMasa->prev_selected_object ) + { + float selected_ene; + float total_ene; + float selected_ratio; + float adaptive_threshold_dB; + float ratio_objects_dB; + float hardswitch_threshold = 0.25f; + + /* Compute the energy of the current and the previous selected object in the current and the previous frame */ + selected_ene = broadband_energy[loudest_object] + broadband_energy[hOMasa->prev_selected_object] + hOMasa->broadband_energy_prev[loudest_object] + hOMasa->broadband_energy_prev[hOMasa->prev_selected_object]; + + /* Compute the energy of all objects and MASA channels in the current and the previous frame */ + total_ene = 0.0f; + for ( i = 0; i < nchan_all_inp; i++ ) + { + total_ene += broadband_energy[i] + hOMasa->broadband_energy_prev[i]; + } + + /* Compute the ratio */ + selected_ratio = selected_ene / ( total_ene + EPSILON ); + + adaptive_threshold_dB = selected_ratio * 9.0f + 1.0f; /* selected ratio = 0 -> 1 dB, selected ratio = 1 -> 10 dB */ + ratio_objects_dB = 10.0f * log10f( hOMasa->broadband_energy_sm[loudest_object] / ( hOMasa->broadband_energy_sm[hOMasa->prev_selected_object] + EPSILON ) ); + + /* Adaptively determine whether to change the separated object. If they are quiet compared to the total energy, change easier, as other signals mask the change. */ + if ( ratio_objects_dB > adaptive_threshold_dB ) + { + if ( selected_ratio < hardswitch_threshold ) /* If low level compared to all audio channels, perform hardswitch */ + { + selected_object = loudest_object; + } + else /* If high level compared to all audio channels, perform switch via fade out fade in */ + { + hOMasa->changing_object = 1; + fade_out_separate_object = 1; + } + } + } + } + + /* Set values for next frame */ + for ( i = 0; i < nchan_all_inp; i++ ) + { + hOMasa->broadband_energy_prev[i] = broadband_energy[i]; + } + hOMasa->prev_selected_object = selected_object; + + /* Separate the selected object */ + *idx_separated_object = selected_object; + mvr2r( data_in_f[selected_object], data_separated_object, input_frame ); + if ( fade_out_separate_object ) + { + v_mult( data_separated_object, hOMasa->fade_out_gain, data_separated_object, input_frame ); + v_mult( data_in_f[selected_object], hOMasa->fade_in_gain, data_in_f[selected_object], input_frame ); + } + else if ( fade_in_separate_object ) + { + v_mult( data_separated_object, hOMasa->fade_in_gain, data_separated_object, input_frame ); + v_mult( data_in_f[selected_object], hOMasa->fade_out_gain, data_in_f[selected_object], input_frame ); + } + else + { + set_zero( data_in_f[selected_object], input_frame ); + } + } + + /* Analysis */ + if ( ism_mode == ISM_MODE_NONE || ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) + { + OMASA_SPATIAL_META OMasaMeta; /* working memory for the ISM-object MASA-parameters */ + OMASA_SPATIAL_META_HANDLE hOMasaMeta; + uint8_t n_bands_orig, n_subframes_orig; + uint8_t numCodingBands_orig, joinedSubframes_orig; + + hOMasaMeta = &OMasaMeta; + hOMasaMeta->num_dirs = 1; /* TODO: hard-coding for now */ + + /* merge MASA directions before adding ISM to the mixture */ + if ( hMasa->config.numberOfDirections == 2 ) + { + n_bands_orig = hMasa->config.numCodingBands; + hMasa->config.numCodingBands = MASA_FREQUENCY_BANDS; + + ivas_masa_combine_directions( hMasa ); + + hMasa->config.numCodingBands = (int8_t) n_bands_orig; + } + + /* force computation into high resolution */ +#ifndef OMASA_FIX_LOW_FS + n_bands_orig = hOMasa->nbands; +#endif + n_subframes_orig = hOMasa->nSubframes; + +#ifndef OMASA_FIX_LOW_FS + hOMasa->nbands = MASA_FREQUENCY_BANDS; +#endif + hOMasa->nSubframes = MAX_PARAM_SPATIAL_SUBFRAMES; + + /* Estimate MASA parameters from the objects */ + /* NB: only first direction is populated */ + /* NB2: in energy_ratios and surround_coherence only first sub-frame contains valid data */ + ivas_omasa_param_est_enc( hOMasa, hMasa, hIsmMeta, data_in_f, hOMasaMeta->directional_meta[0].elevation, hOMasaMeta->directional_meta[0].azimuth, hOMasaMeta->directional_meta[0].energy_ratio[0], hOMasaMeta->directional_meta[0].spread_coherence, hOMasaMeta->common_meta.surround_coherence[0], + hOMasaMeta->common_meta.diffuse_to_total_ratio[0], input_frame, nchan_ism ); + + /* copy energy_ratios and surrCoh from first sub-frame to the remaining ones */ + for ( i = 1; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ ) + { + mvr2r( hOMasaMeta->directional_meta[0].energy_ratio[0], hOMasaMeta->directional_meta[0].energy_ratio[i], MASA_FREQUENCY_BANDS ); + mvr2r( hOMasaMeta->common_meta.surround_coherence[0], hOMasaMeta->common_meta.surround_coherence[i], MASA_FREQUENCY_BANDS ); + mvr2r( hOMasaMeta->common_meta.diffuse_to_total_ratio[0], hOMasaMeta->common_meta.diffuse_to_total_ratio[i], MASA_FREQUENCY_BANDS ); + } + + /* restore resolution parameters */ +#ifndef OMASA_FIX_LOW_FS + hOMasa->nbands = n_bands_orig; +#endif + hOMasa->nSubframes = n_subframes_orig; + + /* perform MASA+ISM merge in full resolution */ + numCodingBands_orig = hMasa->config.numCodingBands; + joinedSubframes_orig = hMasa->config.joinedSubframes; + +#ifndef OMASA_FIX_LOW_FS + hMasa->config.numCodingBands = MASA_FREQUENCY_BANDS; +#else + hMasa->config.numCodingBands = hOMasa->nbands; +#endif + hMasa->config.joinedSubframes = 0; + + ivas_merge_masa_metadata( hMasa, hOMasaMeta ); /* => merge result in hMasa->masaMetadata */ + + hMasa->config.numCodingBands = numCodingBands_orig; + hMasa->config.joinedSubframes = joinedSubframes_orig; + } + else if ( ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) + { + /* Estimate energies and ratios */ + ivas_omasa_energy_and_ratio_est( hOMasa, hMasa, data_in_f, input_frame, nchan_ism ); + } + + /* Move the ISM metadata to the first entry for encoding in the MASA_ONE_OBJ mode */ + if ( ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) + { + hIsmMeta[0]->azimuth = hIsmMeta[*idx_separated_object]->azimuth; + hIsmMeta[0]->elevation = hIsmMeta[*idx_separated_object]->elevation; + } + + /* Downmix */ + ivas_omasa_dmx( data_in_f, data_out_f, input_frame, nchan_transport, nchan_ism, hIsmMeta, hOMasa->prev_object_dm_gains, hOMasa->interpolator ); + + /* Merge transport signals */ + ivas_merge_masa_transports( data_out_f, &( data_in_f[nchan_ism] ), data_in_f, input_frame, nchan_transport ); + + return; +} + + +/*-------------------------------------------------------------------------* + * set_ism_importance_interformat() + * + * Set the importance of particular ISM streams in combined-format coding + *-------------------------------------------------------------------------*/ + +void set_ism_importance_interformat( + const int32_t ism_total_brate, /* i/o: ISms total bitrate */ + const int16_t nchan_transport, /* i : number of transported channels */ + ISM_METADATA_HANDLE hIsmMeta[], /* i/o: ISM metadata handles */ + SCE_ENC_HANDLE hSCE[], /* i/o: SCE encoder handles */ + const float lp_noise_CPE, /* i : LP filtered total noise estimation */ + int16_t ism_imp[] /* o : ISM importance flags */ +) +{ + Encoder_State *st; + int16_t ch, ctype, active_flag; + + for ( ch = 0; ch < nchan_transport; ch++ ) + { + st = hSCE[ch]->hCoreCoder[0]; + + active_flag = st->vad_flag; + + if ( active_flag == 0 ) + { + if ( st->lp_noise > 15 || lp_noise_CPE - st->lp_noise < 30 ) + { + active_flag = 1; + } + } + + /* do not use the low-rate core-coder mode at highest bit-rates */ + if ( ism_total_brate / nchan_transport > IVAS_48k ) + { + active_flag = 1; + } + + ctype = hSCE[ch]->hCoreCoder[0]->coder_type_raw; + + st->low_rate_mode = 0; + if ( active_flag == 0 ) + { + ism_imp[ch] = ISM_INACTIVE_IMP; + st->low_rate_mode = 1; + } + else if ( ctype == INACTIVE || ctype == UNVOICED ) + { + ism_imp[ch] = ISM_LOW_IMP; + } + else if ( ctype == VOICED ) + { + ism_imp[ch] = ISM_MEDIUM_IMP; + } + else /* GENERIC */ + { + ism_imp[ch] = ISM_HIGH_IMP; + } + + hIsmMeta[ch]->ism_metadata_flag = active_flag; /* flag is needed for the MD coding */ + } + + return; +} + + +/*--------------------------------------------------------------------------* + * ivas_set_surplus_brate_enc() + * + * set bit-rate surplus in combined format coding + *--------------------------------------------------------------------------*/ + +void ivas_set_surplus_brate_enc( + Encoder_Struct *st_ivas /* i/o: IVAS encoder structure */ +#ifdef DEBUG_MODE_INFO + , + const int16_t *nb_bits_metadata /* i : number of metadata bits */ +#endif +) +{ + if ( st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) + { + st_ivas->hCPE[0]->brate_surplus = st_ivas->hSCE[0]->element_brate - ivas_interformat_brate( ISM_MASA_MODE_PARAM_ONE_OBJ, 1, st_ivas->hSCE[0]->element_brate, st_ivas->hIsmMetaData[0]->ism_imp, 0 ); + /* note: ISM st->total_brate is iset in ivas_sce_enc() */ + } + else if ( st_ivas->ism_mode == ISM_MASA_MODE_DISC || st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) + { + /* it is already set in ivas_ism_enc() */ + } + else + { + st_ivas->hCPE[0]->brate_surplus = 0; + } + +#ifdef DEBUG_MODE_INFO + if ( st_ivas->hSCE[0] != NULL ) + { + int16_t input_frame = (int16_t) ( st_ivas->hEncoderConfig->input_Fs / FRAMES_PER_SEC ); + float tmpF = 0; + + if ( st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) + { + tmpF += st_ivas->hSCE[0]->hCoreCoder[0]->total_brate + (float) ( nb_bits_metadata[1] * 50 ); + } + else + { + for ( int16_t i = 0; i < st_ivas->hEncoderConfig->nchan_ism; i++ ) + { + tmpF += st_ivas->hSCE[i]->hCoreCoder[0]->total_brate + (float) ( nb_bits_metadata[i + 1] * 50 ); + } + } + tmpF /= 1000.f; + dbgwrite( &tmpF, 4, 1, input_frame, "res/brate_ISM" ); /* == ism_total_brate incl. ISM MD */ + tmpF = st_ivas->hEncoderConfig->ivas_total_brate / 1000.0f - tmpF; + dbgwrite( &tmpF, 4, 1, input_frame, "res/brate_MASA" ); /* == masa_total_brate incl. MASA MD */ + tmpF = nb_bits_metadata[0] * FRAMES_PER_SEC / 1000.0f; + dbgwrite( &tmpF, 4, 1, input_frame, "res/brate_MASA_MD" ); /* == MASA MD bitrate */ + } +#endif + + return; +} + + +/*--------------------------------------------------------------------------* + * ivas_omasa_ener_brate() + * + * + *--------------------------------------------------------------------------*/ + +/*! r: OMASA energy bitrate flag */ +int16_t ivas_omasa_ener_brate( + const int16_t nchan_ism, /* i : number of ISMs */ + const int32_t ivas_total_brate, /* i : IVAS total bitrate */ + float data_f[][L_FRAME48k], /* i : Input / transport audio signals */ + const int16_t input_frame /* i : Input frame size */ +) +{ + int16_t i, flag_omasa_ener_brate; + float energy_ism, energy_masa; + + flag_omasa_ener_brate = 0; + + if ( nchan_ism >= 3 && ivas_total_brate == IVAS_128k ) + { + energy_ism = 0.0f; + for ( i = 0; i < nchan_ism; i++ ) + { + energy_ism += sum2_f( data_f[i], input_frame ); + } + + energy_masa = 0.0f; + for ( i = nchan_ism; i < nchan_ism + MASA_MAXIMUM_DIRECTIONS; i++ ) + { + energy_masa += sum2_f( data_f[i], input_frame ); + } + + energy_ism = energy_ism / ( energy_masa + 1.0f ) * 2.0f / (float) ( nchan_ism ); + + if ( energy_ism < 1.0f ) + { + flag_omasa_ener_brate = 1; + } + } + + return flag_omasa_ener_brate; +} + + +/*--------------------------------------------------------------------------* + * Local functions + *--------------------------------------------------------------------------*/ + +/* Estimate MASA parameters from the objects */ +static void ivas_omasa_param_est_enc( + OMASA_ENC_HANDLE hOMasa, + MASA_ENCODER_HANDLE hMasa, + ISM_METADATA_HANDLE hIsmMeta[], + float data_f[][L_FRAME48k], + float elevation_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], + float azimuth_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], + float energyRatio[MASA_FREQUENCY_BANDS], + float spreadCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], + float surroundingCoherence[MASA_FREQUENCY_BANDS], + float diffuseness_m[MASA_FREQUENCY_BANDS], + const int16_t input_frame, + const int16_t nchan_ism ) +{ + float reference_power[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + int16_t ts, i, j, d, k; + int16_t num_freq_bins, num_freq_bands, index; + float dir_v[DIRAC_NUM_DIMS]; + int16_t l_ts; + float Chnl_RealBuffer[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX]; + float Chnl_ImagBuffer[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX]; + float Foa_RealBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX]; + float Foa_ImagBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX]; + float intensity_real[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS]; + float direction_vector[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS]; + float diffuseness_vector[MASA_FREQUENCY_BANDS]; + int16_t band_m_idx, block_m_idx; + float renormalization_factor_diff[MASA_FREQUENCY_BANDS]; + float norm_tmp; + int16_t mrange[2], brange[2]; + + num_freq_bins = hOMasa->cldfbAnaEnc[0]->no_channels; + num_freq_bands = hOMasa->nbands; + l_ts = input_frame / CLDFB_NO_COL_MAX; + + /* Need to initialize renormalization_factors, and variables to be normalized */ + set_zero( renormalization_factor_diff, hOMasa->nbands ); + set_zero( diffuseness_m, hOMasa->nbands ); + + /* Compute ISM to FOA matrices */ + for ( i = 0; i < nchan_ism; i++ ) + { + hOMasa->chnlToFoaMtx[0][i] = 1.0f; + hOMasa->chnlToFoaMtx[1][i] = sinf( ( hIsmMeta[i]->azimuth / 180.0f * EVS_PI ) ) * cosf( ( hIsmMeta[i]->elevation / 180.0f * EVS_PI ) ); + hOMasa->chnlToFoaMtx[2][i] = sinf( ( hIsmMeta[i]->elevation / 180.0f * EVS_PI ) ); + hOMasa->chnlToFoaMtx[3][i] = cosf( ( hIsmMeta[i]->azimuth / 180.0f * EVS_PI ) ) * cosf( ( hIsmMeta[i]->elevation / 180.0f * EVS_PI ) ); + } + + /* do processing over all CLDFB time slots */ + for ( block_m_idx = 0; block_m_idx < hOMasa->nSubframes; block_m_idx++ ) + { + mrange[0] = hOMasa->block_grouping[block_m_idx]; + mrange[1] = hOMasa->block_grouping[block_m_idx + 1]; + + for ( band_m_idx = 0; band_m_idx < hOMasa->nbands; band_m_idx++ ) + { + hOMasa->direction_vector_m[0][block_m_idx][band_m_idx] = 0.0f; + hOMasa->direction_vector_m[1][block_m_idx][band_m_idx] = 0.0f; + hOMasa->direction_vector_m[2][block_m_idx][band_m_idx] = 0.0f; + } + + set_zero( hMasa->data.energy_ism[block_m_idx], num_freq_bands ); + + for ( ts = mrange[0]; ts < mrange[1]; ts++ ) + { + for ( i = 0; i < nchan_ism; i++ ) + { + cldfbAnalysis_ts( &( data_f[i][l_ts * ts] ), Chnl_RealBuffer[i], Chnl_ImagBuffer[i], l_ts, hOMasa->cldfbAnaEnc[i] ); + } + + /* Compute energy */ + for ( i = 0; i < num_freq_bands; i++ ) + { + brange[0] = hOMasa->band_grouping[i]; + brange[1] = hOMasa->band_grouping[i + 1]; + for ( j = brange[0]; j < brange[1]; j++ ) + { + for ( k = 0; k < nchan_ism; k++ ) + { + hMasa->data.energy_ism[block_m_idx][i] += Chnl_RealBuffer[k][j] * Chnl_RealBuffer[k][j] + Chnl_ImagBuffer[k][j] * Chnl_ImagBuffer[k][j]; + } + } + } + + /* Compute FOA */ + /* W */ + mvr2r( Chnl_RealBuffer[0], Foa_RealBuffer[0], num_freq_bins ); + mvr2r( Chnl_ImagBuffer[0], Foa_ImagBuffer[0], num_freq_bins ); + for ( i = 1; i < nchan_ism; i++ ) + { + v_add( Chnl_RealBuffer[i], Foa_RealBuffer[0], Foa_RealBuffer[0], num_freq_bins ); + v_add( Chnl_ImagBuffer[i], Foa_ImagBuffer[0], Foa_ImagBuffer[0], num_freq_bins ); + } + + /* Y */ + v_multc( Chnl_RealBuffer[0], hOMasa->chnlToFoaMtx[1][0], Foa_RealBuffer[1], num_freq_bins ); + v_multc( Chnl_ImagBuffer[0], hOMasa->chnlToFoaMtx[1][0], Foa_ImagBuffer[1], num_freq_bins ); + for ( i = 1; i < nchan_ism; i++ ) + { + v_multc_acc( Chnl_RealBuffer[i], hOMasa->chnlToFoaMtx[1][i], Foa_RealBuffer[1], num_freq_bins ); + v_multc_acc( Chnl_ImagBuffer[i], hOMasa->chnlToFoaMtx[1][i], Foa_ImagBuffer[1], num_freq_bins ); + } + + /* Z */ + v_multc( Chnl_RealBuffer[0], hOMasa->chnlToFoaMtx[2][0], Foa_RealBuffer[2], num_freq_bins ); + v_multc( Chnl_ImagBuffer[0], hOMasa->chnlToFoaMtx[2][0], Foa_ImagBuffer[2], num_freq_bins ); + for ( i = 1; i < nchan_ism; i++ ) + { + v_multc_acc( Chnl_RealBuffer[i], hOMasa->chnlToFoaMtx[2][i], Foa_RealBuffer[2], num_freq_bins ); + v_multc_acc( Chnl_ImagBuffer[i], hOMasa->chnlToFoaMtx[2][i], Foa_ImagBuffer[2], num_freq_bins ); + } + + /* X */ + v_multc( Chnl_RealBuffer[0], hOMasa->chnlToFoaMtx[3][0], Foa_RealBuffer[3], num_freq_bins ); + v_multc( Chnl_ImagBuffer[0], hOMasa->chnlToFoaMtx[3][0], Foa_ImagBuffer[3], num_freq_bins ); + for ( i = 1; i < nchan_ism; i++ ) + { + v_multc_acc( Chnl_RealBuffer[i], hOMasa->chnlToFoaMtx[3][i], Foa_RealBuffer[3], num_freq_bins ); + v_multc_acc( Chnl_ImagBuffer[i], hOMasa->chnlToFoaMtx[3][i], Foa_ImagBuffer[3], num_freq_bins ); + } + + /* Direction estimation */ + computeIntensityVector_enc( hOMasa->band_grouping, Foa_RealBuffer, Foa_ImagBuffer, num_freq_bands, intensity_real ); + computeDirectionVectors( intensity_real[0], intensity_real[1], intensity_real[2], 0, num_freq_bands, direction_vector[0], direction_vector[1], direction_vector[2] ); + + /* Power estimation for diffuseness */ + computeReferencePower_omasa( hOMasa->band_grouping, Foa_RealBuffer, Foa_ImagBuffer, reference_power[ts], 0, num_freq_bands ); + + /* Fill buffers of length "averaging_length" time slots for intensity and energy */ + hOMasa->index_buffer_intensity = ( hOMasa->index_buffer_intensity % DIRAC_NO_COL_AVG_DIFF ) + 1; /* averaging_length = 32 */ + index = hOMasa->index_buffer_intensity; + for ( i = 0; i < DIRAC_NUM_DIMS; i++ ) + { + /* only real part needed */ + mvr2r( intensity_real[i], &( hOMasa->buffer_intensity_real[i][index - 1][0] ), num_freq_bands ); + } + mvr2r( reference_power[ts], &( hOMasa->buffer_energy[( index - 1 ) * num_freq_bands] ), num_freq_bands ); + + computeDiffuseness( hOMasa->buffer_intensity_real, hOMasa->buffer_energy, num_freq_bands, diffuseness_vector ); + + for ( band_m_idx = 0; band_m_idx < hOMasa->nbands; band_m_idx++ ) + { + norm_tmp = reference_power[ts][band_m_idx] * ( 1 - diffuseness_vector[band_m_idx] ); + + hOMasa->direction_vector_m[0][block_m_idx][band_m_idx] += norm_tmp * direction_vector[0][band_m_idx]; + hOMasa->direction_vector_m[1][block_m_idx][band_m_idx] += norm_tmp * direction_vector[1][band_m_idx]; + hOMasa->direction_vector_m[2][block_m_idx][band_m_idx] += norm_tmp * direction_vector[2][band_m_idx]; + + diffuseness_m[band_m_idx] += reference_power[ts][band_m_idx] * diffuseness_vector[band_m_idx]; + renormalization_factor_diff[band_m_idx] += reference_power[ts][band_m_idx]; + } + } + + for ( band_m_idx = 0; band_m_idx < hOMasa->nbands; band_m_idx++ ) + { + for ( d = 0; d < DIRAC_NUM_DIMS; d++ ) + { + dir_v[d] = hOMasa->direction_vector_m[d][block_m_idx][band_m_idx]; + } + ivas_qmetadata_direction_vector_to_azimuth_elevation( dir_v, &azimuth_m_values[block_m_idx][band_m_idx], &elevation_m_values[block_m_idx][band_m_idx] ); + } + /* Set coherences to zero, as this mode is used at lowest bit rates where the coherences are not transmitted */ + for ( band_m_idx = 0; band_m_idx < hOMasa->nbands; band_m_idx++ ) + { + spreadCoherence[block_m_idx][band_m_idx] = 0.0f; + surroundingCoherence[band_m_idx] = 0.0f; + } + } + + /* Determine energy ratios */ + for ( band_m_idx = 0; band_m_idx < hOMasa->nbands; band_m_idx++ ) + { + if ( renormalization_factor_diff[band_m_idx] > EPSILON ) + { + diffuseness_m[band_m_idx] /= renormalization_factor_diff[band_m_idx]; + } + else + { + diffuseness_m[band_m_idx] = 0.0f; + } + + energyRatio[band_m_idx] = 1.0f - diffuseness_m[band_m_idx]; + } + + return; +} + + +/* Estimate energies and ratios */ +static void ivas_omasa_energy_and_ratio_est( + OMASA_ENC_HANDLE hOMasa, + MASA_ENCODER_HANDLE hMasa, + float data_f[][L_FRAME48k], + const int16_t input_frame, + const int16_t nchan_inp ) +{ + int16_t ts, i, j, k; + int16_t num_freq_bands; + int16_t l_ts; + float Chnl_RealBuffer[MAX_NUM_OBJECTS][CLDFB_NO_CHANNELS_MAX]; + float Chnl_ImagBuffer[MAX_NUM_OBJECTS][CLDFB_NO_CHANNELS_MAX]; + int16_t block_m_idx; + int16_t mrange[2], brange[2]; + float tftile_energy; + float ism_ratio_sum; + + num_freq_bands = hOMasa->nbands; + l_ts = input_frame / CLDFB_NO_COL_MAX; + + /* do processing over all CLDFB time slots */ + for ( block_m_idx = 0; block_m_idx < hOMasa->nSubframes; block_m_idx++ ) + { + mrange[0] = hOMasa->block_grouping[block_m_idx]; + mrange[1] = hOMasa->block_grouping[block_m_idx + 1]; + + /* Reset variable */ + for ( i = 0; i < hOMasa->nbands; i++ ) + { + set_zero( hMasa->data.energy_ratio_ism[block_m_idx][i], nchan_inp ); + } + set_zero( hMasa->data.energy_ism[block_m_idx], num_freq_bands ); + + /* Compute CLDFB */ + for ( ts = mrange[0]; ts < mrange[1]; ts++ ) + { + for ( i = 0; i < nchan_inp; i++ ) + { + cldfbAnalysis_ts( &( data_f[i][l_ts * ts] ), Chnl_RealBuffer[i], Chnl_ImagBuffer[i], l_ts, hOMasa->cldfbAnaEnc[i] ); + } + + /* Compute energy */ + for ( i = 0; i < num_freq_bands; i++ ) + { + brange[0] = hOMasa->band_grouping[i]; + brange[1] = hOMasa->band_grouping[i + 1]; + for ( j = brange[0]; j < brange[1]; j++ ) + { + for ( k = 0; k < nchan_inp; k++ ) + { + tftile_energy = Chnl_RealBuffer[k][j] * Chnl_RealBuffer[k][j] + Chnl_ImagBuffer[k][j] * Chnl_ImagBuffer[k][j]; + hMasa->data.energy_ism[block_m_idx][i] += tftile_energy; + hMasa->data.energy_ratio_ism[block_m_idx][i][k] += tftile_energy; + } + } + } + } + + /* Compute ISM energy ratios */ + for ( i = 0; i < num_freq_bands; i++ ) + { + ism_ratio_sum = 0.0f; + for ( j = 0; j < nchan_inp; j++ ) + { + hMasa->data.energy_ratio_ism[block_m_idx][i][j] /= ( hMasa->data.energy_ism[block_m_idx][i] + EPSILON ); + ism_ratio_sum += hMasa->data.energy_ratio_ism[block_m_idx][i][j]; + } + + if ( ism_ratio_sum == 0.0f ) + { + float temp_ism_ratio = 1.0f / ( (float) nchan_inp ); + for ( j = 0; j < nchan_inp; j++ ) + { + hMasa->data.energy_ratio_ism[block_m_idx][i][j] = temp_ism_ratio; + } + } + } + hMasa->data.nchan_ism = nchan_inp; + } + + return; +} + + +/* Compute downmix */ +static void ivas_omasa_dmx( + float data_in_f[][L_FRAME48k], + float data_out_f[][L_FRAME48k], + const int16_t input_frame, + const int16_t nchan_transport, + const int16_t nchan_ism, + ISM_METADATA_HANDLE hIsmMeta[], + float prev_gains[][MASA_MAX_TRANSPORT_CHANNELS], + const float interpolator[L_FRAME48k] ) +{ + int16_t i, j, k; + float azimuth, elevation; + float gains[MASA_MAX_TRANSPORT_CHANNELS]; + float g1, g2; + + + for ( i = 0; i < nchan_transport; i++ ) + { + set_zero( data_out_f[i], input_frame ); + } + + for ( i = 0; i < nchan_ism; i++ ) + { + azimuth = hIsmMeta[i]->azimuth; + elevation = hIsmMeta[i]->elevation; + + ivas_get_stereo_panning_gains( azimuth, elevation, gains ); + + /* Downmix using the panning gains */ + for ( j = 0; j < nchan_transport; j++ ) + { + if ( fabsf( gains[j] ) > 0.0 || fabsf( prev_gains[i][j] ) > 0.0f ) + { + for ( k = 0; k < input_frame; k++ ) + { + g1 = interpolator[k]; + g2 = 1.0f - g1; + data_out_f[j][k] += ( g1 * gains[j] + g2 * prev_gains[i][j] ) * data_in_f[i][k]; + } + } + prev_gains[i][j] = gains[j]; + } + } + + return; +} + + +static void computeIntensityVector_enc( + const int16_t *band_grouping, + float Cldfb_RealBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX], + float Cldfb_ImagBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX], + const int16_t num_frequency_bands, + float intensity_real[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS] ) +{ + /* Reminder + * X = a + ib; Y = c + id + * X*Y = ac - bd + i(ad +bc) + */ + int16_t i, j; + float real, img; + int16_t brange[2]; + + for ( i = 0; i < num_frequency_bands; i++ ) + { + brange[0] = band_grouping[i]; + brange[1] = band_grouping[i + 1]; + + intensity_real[0][i] = 0; + intensity_real[1][i] = 0; + intensity_real[2][i] = 0; + + for ( j = brange[0]; j < brange[1]; j++ ) + { + real = Cldfb_RealBuffer[0][j]; + img = Cldfb_ImagBuffer[0][j]; + intensity_real[0][i] += Cldfb_RealBuffer[3][j] * real + Cldfb_ImagBuffer[3][j] * img; /* Intensity is XYZ order, audio is WYZX order. */ + intensity_real[1][i] += Cldfb_RealBuffer[1][j] * real + Cldfb_ImagBuffer[1][j] * img; + intensity_real[2][i] += Cldfb_RealBuffer[2][j] * real + Cldfb_ImagBuffer[2][j] * img; + } + } + + return; +} + + +static void computeReferencePower_omasa( + const int16_t *band_grouping, /* i : Band grouping for estimation */ + float Cldfb_RealBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX], /* i : Real part of input signal */ + float Cldfb_ImagBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX], /* i : Imag part of input signal */ + float *reference_power, /* o : Estimated power */ + const int16_t enc_param_start_band, /* i : first band to process */ + const int16_t num_freq_bands /* i : Number of frequency bands */ +) +{ + int16_t brange[2]; + int16_t ch_idx, i, j; + + for ( i = 0; i < num_freq_bands; i++ ) + { + brange[0] = band_grouping[i + enc_param_start_band]; + brange[1] = band_grouping[i + enc_param_start_band + 1]; + reference_power[i] = 0; + + for ( ch_idx = 0; ch_idx < FOA_CHANNELS; ch_idx++ ) + { + /* abs()^2 */ + for ( j = brange[0]; j < brange[1]; j++ ) + { + reference_power[i] += ( Cldfb_RealBuffer[ch_idx][j] * Cldfb_RealBuffer[ch_idx][j] ) + ( Cldfb_ImagBuffer[ch_idx][j] * Cldfb_ImagBuffer[ch_idx][j] ); + } + } + } + + v_multc( reference_power, 0.5f, reference_power, num_freq_bands ); + + return; +} + +#endif /* MASA_AND_OBJECTS */ diff --git a/lib_enc/ivas_qmetadata_enc.c b/lib_enc/ivas_qmetadata_enc.c index 7cf68d677dd3939231d2cd2680cc1bde6285eaa7..a811ed164dfd8f004d842a3fb2930a055429f445 100644 --- a/lib_enc/ivas_qmetadata_enc.c +++ b/lib_enc/ivas_qmetadata_enc.c @@ -63,9 +63,15 @@ static int16_t ivas_qmetadata_entropy_encode_dir( BSTR_ENC_HANDLE hMetaData, IVA static int16_t ivas_qmetadata_raw_encode_dir( BSTR_ENC_HANDLE hMetaData, IVAS_QDIRECTION *q_direction, const int16_t nbands, const int16_t start_band ); -static int16_t ivas_qmetadata_encode_extended_gr_length( const uint16_t value, const uint16_t alphabet_size, const int16_t gr_param ); +#ifndef MASA_AND_OBJECTS +static +#endif + int16_t + ivas_qmetadata_encode_extended_gr_length( const uint16_t value, const uint16_t alphabet_size, const int16_t gr_param ); +#ifndef MASA_AND_OBJECTS static void ivas_qmetadata_encode_extended_gr( BSTR_ENC_HANDLE hMetaData, const uint16_t value, const uint16_t alphabet_size, const int16_t gr_param ); +#endif static int16_t ivas_qmetadata_get_optimal_gr_param( uint16_t *unsigned_data, const int16_t count, const int16_t gr_param_count, int16_t *opt_gr_size ); @@ -129,6 +135,14 @@ static void ivas_qmetadata_reorder_2dir_bands_hr( IVAS_QMETADATA_HANDLE hQMetaDa static int16_t ivas_qmetadata_quantize_coherence_hr_512( IVAS_QMETADATA *hQMetaData, const int16_t idx_d, const int16_t all_coherence_zero, BSTR_ENC_HANDLE hMetaData, const int16_t bits_coh ); +#ifdef MASA_AND_OBJECTS +static int16_t write_stream_dct_coeffs_omasa( int16_t *q_idx, const int16_t len_stream, BSTR_ENC_HANDLE hMetaData, const int16_t first_line, const int16_t low_bitrate_mode ); + +static int16_t find_optimal_GR_order( const int16_t *q_idx, const int16_t len, int16_t *GR ); + +static int16_t find_optimal_GR_orders( const int16_t *q_idx, const int16_t len, const int16_t len_max_GR1, int16_t *GR1, int16_t *GR2, int16_t *i_min ); +#endif + /*-----------------------------------------------------------------------* * ivas_qmetadata_enc_encode() @@ -759,6 +773,7 @@ ivas_error ivas_qmetadata_enc_encode_hr_384_512( bits_no_dirs_coh += #endif write_2dir_info( hMetaData, hQMetaData->twoDirBands, hQMetaData->q_direction[0].cfg.nbands, hQMetaData->numTwoDirBands ); +#ifdef FIX_566_2DIR_MASA_384K d = 0; for ( i = hQMetaData->q_direction[1].cfg.start_band; i < hQMetaData->q_direction[1].cfg.nbands; i++ ) { @@ -775,6 +790,7 @@ ivas_error ivas_qmetadata_enc_encode_hr_384_512( d++; } } +#endif for ( i = hQMetaData->numTwoDirBands; i < hQMetaData->q_direction[0].cfg.nbands; i++ ) { set_f( hQMetaData->q_direction[1].band_data[i].energy_ratio, 0.0f, hQMetaData->q_direction[1].cfg.nblocks ); @@ -1620,7 +1636,9 @@ static void ivas_qmetadata_quantize_diffuseness_nrg_ratios_hr_512( } } #else +#ifdef FIX_566_2DIR_MASA_384K float ratioSum; +#endif for ( j = hQMetaData->q_direction[1].cfg.start_band; j < hQMetaData->q_direction[1].cfg.nbands; ++j ) { for ( k = 0; k < hQMetaData->q_direction[1].cfg.nblocks; k++ ) @@ -1629,12 +1647,19 @@ static void ivas_qmetadata_quantize_diffuseness_nrg_ratios_hr_512( push_next_indice( hMetaData, index, MASA_BITS_ER_HR ); hQMetaData->q_direction[1].band_data[j].energy_ratio_index[k] = index; hQMetaData->q_direction[1].band_data[j].energy_ratio[k] = 1.0f - diffuseness_reconstructions_hr[index]; +#ifdef FIX_566_2DIR_MASA_384K ratioSum = hQMetaData->q_direction[0].band_data[j].energy_ratio[k] + hQMetaData->q_direction[1].band_data[j].energy_ratio[k]; if ( ratioSum > 1.0f ) { hQMetaData->q_direction[0].band_data[j].energy_ratio[k] /= ratioSum; hQMetaData->q_direction[1].band_data[j].energy_ratio[k] /= ratioSum; } +#else + if ( hQMetaData->q_direction[1].band_data[j].energy_ratio[k] > 1.0f - hQMetaData->q_direction[0].band_data[j].energy_ratio[k] ) + { + hQMetaData->q_direction[1].band_data[j].energy_ratio[k] = 1.0f - hQMetaData->q_direction[0].band_data[j].energy_ratio[k]; + } +#endif needed_bits[1] += MASA_BITS_ER_HR; hQMetaData->q_direction[1].band_data[j].bits_sph_idx[k] = bits_dir_hr; } @@ -3162,10 +3187,14 @@ static int16_t ivas_qmetadata_get_optimal_gr_param( * *------------------------------------------------------------------------*/ -static int16_t ivas_qmetadata_encode_extended_gr_length( - const uint16_t value, - const uint16_t alphabet_size, - const int16_t gr_param ) +#ifndef MASA_AND_OBJECTS +static +#endif + int16_t + ivas_qmetadata_encode_extended_gr_length( + const uint16_t value, + const uint16_t alphabet_size, + const int16_t gr_param ) { uint16_t msb_alphabet_size; int16_t bits; @@ -3305,11 +3334,15 @@ static int16_t ivas_qmetadata_reorder_azimuth_index( * *------------------------------------------------------------------------*/ -static void ivas_qmetadata_encode_extended_gr( - BSTR_ENC_HANDLE hMetaData, - const uint16_t value, - const uint16_t alphabet_size, - const int16_t gr_param ) +#ifndef MASA_AND_OBJECTS +static +#endif + void + ivas_qmetadata_encode_extended_gr( + BSTR_ENC_HANDLE hMetaData, + const uint16_t value, + const uint16_t alphabet_size, + const int16_t gr_param ) { uint16_t msb_alphabet_size; uint16_t msb, lsb, cnt; @@ -3504,7 +3537,7 @@ static int16_t truncGR0( *-------------------------------------------------------------------*/ static int16_t truncGR0_chan( - float *data, + const float *data, float *data_hat, uint16_t *data_idx, const int16_t len, @@ -6057,3 +6090,495 @@ static float direction_distance( return d / (float) ( dim1 * dim2 ); } #endif + +#ifdef MASA_AND_OBJECTS + +static int16_t divide_GR_orders( + const int16_t *q_idx, + const int16_t GR1, + const int16_t GR2, + const int16_t len, + const int16_t len_max_GR1, + int16_t *i_min ) +{ + int16_t nb_GR_min; + int16_t i, j, nb_GR; + nb_GR_min = 1000; + *i_min = -1; + for ( i = 0; i < min( len_max_GR1, len ); i++ ) + { + nb_GR = 0; + + for ( j = 0; j <= i; j++ ) + { + nb_GR += ivas_qmetadata_encode_extended_gr_length( q_idx[j], 100, GR1 ); + } + for ( j = i + 1; j < len; j++ ) + { + nb_GR += ivas_qmetadata_encode_extended_gr_length( q_idx[j], 100, GR2 ); + } + + if ( nb_GR < nb_GR_min ) + { + nb_GR_min = nb_GR; + *i_min = i + 1; + } + } + + return nb_GR_min; +} + + +static int16_t find_optimal_GR_order( + const int16_t *q_idx, + const int16_t len, + int16_t *GR ) +{ + int16_t nb_GR_0, nb_GR_1; + int16_t i; + /* find optimum length of the part encoded with GR2 */ + nb_GR_0 = 0; + nb_GR_1 = 0; + for ( i = 0; i < len; i++ ) + { + nb_GR_0 += ivas_qmetadata_encode_extended_gr_length( q_idx[i], 100, 0 ); + nb_GR_1 += ivas_qmetadata_encode_extended_gr_length( q_idx[i], 100, 1 ); + } + + if ( nb_GR_0 < nb_GR_1 ) + { + *GR = 0; + return nb_GR_0; + } + else + { + *GR = 1; + + return nb_GR_1; + } +} + + +static int16_t find_optimal_GR_orders( + const int16_t *q_idx, + const int16_t len, + const int16_t len_max_GR1, + int16_t *GR1, + int16_t *GR2, + int16_t *i_min ) +{ + int16_t nb_GR_20, nb_GR_21, nb_GR_10, nb_GR_min; + int16_t i_min_20, i_min_21, i_min_10; + /* find optimum length of the part encoded with GR2 */ + nb_GR_20 = divide_GR_orders( q_idx, 2, 0, len, len_max_GR1, &i_min_20 ); + nb_GR_21 = divide_GR_orders( q_idx, 2, 1, len, len_max_GR1, &i_min_21 ); + nb_GR_10 = divide_GR_orders( q_idx, 1, 0, len, len_max_GR1, &i_min_10 ); + + if ( nb_GR_20 < nb_GR_21 && nb_GR_20 < nb_GR_10 ) + { + *GR1 = 2; + *GR2 = 0; + nb_GR_min = nb_GR_20; + *i_min = i_min_20; + } + else + { + if ( nb_GR_21 < nb_GR_20 && nb_GR_21 < nb_GR_10 ) + { + *GR1 = 2; + *GR2 = 1; + nb_GR_min = nb_GR_21; + *i_min = i_min_21; + } + else + { + *GR1 = 1; + *GR2 = 0; + nb_GR_min = nb_GR_10; + *i_min = i_min_10; + } + } + + return nb_GR_min; +} + + +static int16_t write_stream_dct_coeffs_omasa( + int16_t *q_idx, /* i: array of indexes to be written */ + const int16_t len_stream, /* i: array length */ + BSTR_ENC_HANDLE hMetaData, /* i/o: metadata bitstream */ + const int16_t first_line, /* i: is first line of the matrix? 1/0*/ + const int16_t low_bitrate_mode /* i: is low bitrate mode? if yes, limit the number of bits written */ +) +{ + int16_t nb_bits = 0, bits_pos; + uint16_t nb_GR_min; + int16_t i, j; + int16_t changed, update_needed; + + int16_t GR1, GR2, i_min; + int16_t max_bits; + + bits_pos = hMetaData->nb_bits_tot; + if ( low_bitrate_mode == 1 ) + { + max_bits = 50; /* To do : find optimal allowed value*/ + } + else + { + max_bits = 1000; + } + /* write DCT 0 component */ + /* write sign only if not the very first DCT coeff */ + if ( first_line == 0 ) + { + if ( q_idx[0] > 0 ) + { + push_next_indice( hMetaData, 1, 1 ); + push_next_indice( hMetaData, q_idx[0], BITS_MASA2TOTTAL_DCT0 ); + } + else + { + push_next_indice( hMetaData, 0, 1 ); + push_next_indice( hMetaData, -q_idx[0], BITS_MASA2TOTTAL_DCT0 ); + } + nb_bits += BITS_MASA2TOTTAL_DCT0 + 1; + } + else + { + push_next_indice( hMetaData, q_idx[0], BITS_MASA2TOTTAL_DCT0 ); + nb_bits += BITS_MASA2TOTTAL_DCT0; + } + + + if ( q_idx[0] != 0 ) + { + i_min = 1; + GR2 = 0; + if ( len_stream >= 8 ) + { + nb_GR_min = find_optimal_GR_orders( &q_idx[1], len_stream - 1, 15, &GR1, &GR2, &i_min ); + } + else + { + nb_GR_min = find_optimal_GR_order( &q_idx[1], len_stream - 1, &GR1 ); + } + + assert( nb_GR_min < 1000 ); + changed = 1; + update_needed = 0; + while ( len_stream >= 8 && nb_GR_min > max_bits && changed >= 1 ) + { + update_needed = 1; + changed = 0; + for ( j = len_stream - 1; j > 6; j-- ) + { + if ( q_idx[j] >= 2 ) + { + + if ( j > i_min ) + { + changed = 1; + nb_GR_min -= ivas_qmetadata_encode_extended_gr_length( q_idx[j], 100, GR2 ); + q_idx[j] -= 2; + nb_GR_min += ivas_qmetadata_encode_extended_gr_length( q_idx[j], 100, GR2 ); + } + else + { + changed = 1; + nb_GR_min -= ivas_qmetadata_encode_extended_gr_length( q_idx[j], 100, GR1 ); + q_idx[j] -= 2; + nb_GR_min += ivas_qmetadata_encode_extended_gr_length( q_idx[j], 100, 0 ); + } + } + else if ( q_idx[j] == 1 ) + { + if ( j > i_min ) + { + changed = 1; + nb_GR_min -= ivas_qmetadata_encode_extended_gr_length( q_idx[j], 100, GR2 ); + q_idx[j] -= 1; + + nb_GR_min += ivas_qmetadata_encode_extended_gr_length( q_idx[j], 100, GR2 ); + } + else + { + changed = 1; + nb_GR_min -= ivas_qmetadata_encode_extended_gr_length( q_idx[j], 100, GR1 ); + q_idx[j] -= 1; + nb_GR_min += ivas_qmetadata_encode_extended_gr_length( q_idx[j], 100, 0 ); + } + } + if ( nb_GR_min < max_bits ) + { + break; + } + } + } + if ( update_needed == 1 ) + { + /* re-calculate */ + /* find optimum length of the part encoded with GR2 */ + nb_GR_min = find_optimal_GR_orders( &q_idx[1], len_stream - 1, 15, &GR1, &GR2, &i_min ); + } + + if ( len_stream >= 8 ) + { + /* write number of indexes encoded with GR2 on 4 bits */ + push_next_indice( hMetaData, i_min, 4 ); + nb_bits += 4; + /* write GR orders */ + push_next_indice( hMetaData, GR1 - 1, 1 ); + nb_bits += 1; + if ( GR1 == 2 ) + { + push_next_indice( hMetaData, GR2, 1 ); + nb_bits += 1; + } + + /* write GR data */ + for ( i = 1; i <= i_min; i++ ) + { + ivas_qmetadata_encode_extended_gr( hMetaData, q_idx[i], 100, GR1 ); + } + + for ( i = i_min + 1; i < len_stream; i++ ) + { + ivas_qmetadata_encode_extended_gr( hMetaData, q_idx[i], 100, GR2 ); + } + } + else + { + /* len_stream <= 8 */ + /* write GR order */ + push_next_indice( hMetaData, GR1, 1 ); + nb_bits += 1; + for ( i = 1; i < len_stream; i++ ) + { + ivas_qmetadata_encode_extended_gr( hMetaData, q_idx[i], 100, GR1 ); + } + } + + nb_bits += nb_GR_min; + + assert( nb_bits == ( hMetaData->nb_bits_tot - bits_pos ) ); + } + + return nb_bits; +} + + +/*------------------------------------------------------------------------- + * encode_masa_to_total() + * + *------------------------------------------------------------------------*/ + +void encode_masa_to_total( + IVAS_QMETADATA_HANDLE hQMetaData, + BSTR_ENC_HANDLE hMetaData, + const int16_t low_bitrate_mode, + const int16_t nbands, + const int16_t nblocks ) +{ + int16_t i, j, k; + 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 DEBUG_MODE_QMETADATA + static FILE *pF = NULL; + static FILE *pF_ratio = NULL; + + if ( pF == NULL ) + pF = fopen( "./res/qmetadata_ism_qidx__enc.txt", "w" ); + if ( pF_ratio == NULL ) + pF_ratio = fopen( "./res/qmetadata_masa2tot_enc.txt", "w" ); + +#endif + + bits_pos = hMetaData->nb_bits_tot; + k = 0; + for ( i = 0; i < nbands; i++ ) + { + for ( j = 0; j < nblocks; j++ ) + { + data[k] = hQMetaData->masa_to_total_energy_ratio[j][i]; + k++; + } + } + + /* DCT2 transform */ + n_streams = 1; + len_stream = nbands * nblocks; + switch ( len_stream ) + { + case 4: + matrix_product( dct4, nblocks, nblocks, 0, data, 1, nblocks, 1, dct_data ); + n_streams = 1; + len_stream = 4; + break; + case 5: + matrix_product( dct5, nbands, nbands, 0, data, 1, nbands, 1, dct_data ); + n_streams = 1; + len_stream = nbands; + break; + case 8: + matrix_product( dct8, nbands, nbands, 0, data, 1, nbands, 1, dct_data ); + n_streams = 1; + len_stream = nbands; + break; + case 12: + matrix_product( dct12, nbands, nbands, 0, data, 1, nbands, 1, dct_data ); + n_streams = 1; + len_stream = nbands; + break; + case 20: + matrix_product( dct5, nbands, nbands, 0, data, nblocks, nbands, 1, dct_data_tmp ); + matrix_product( dct_data_tmp, nbands, nblocks, 0, dct4, nblocks, nblocks, 1, dct_data ); + n_streams = 1; + len_stream = nbands * nblocks; + break; + case 32: + matrix_product( dct8, nbands, nbands, 0, data, nblocks, nbands, 1, dct_data_tmp ); + matrix_product( dct_data_tmp, nbands, nblocks, 0, dct4, nblocks, nblocks, 1, dct_data ); + n_streams = nblocks; + len_stream = nbands; + break; + default: + printf( "Incorrect number of coefficients for OMASA.\n" ); + break; + } + + for ( k = 0; k < n_streams; k++ ) + { + j = k * len_stream; + /* quantize with fixed common step */ + q_idx[j] = (int16_t) rintf( dct_data[j] / step ); + + if ( q_idx[j] > ( ( 1 << BITS_MASA2TOTTAL_DCT0 ) - 1 ) ) /* limit DCT0 to BITS_MASA2TOTTAL_DCT0 bit representation */ + { + q_idx[j] = ( ( 1 << BITS_MASA2TOTTAL_DCT0 ) - 1 ); + } + + q_dct_data[j] = step * q_idx[j]; + + if ( q_idx[j] == 0 ) + { + set_s( &q_idx[j], 0, len_stream ); + set_zero( &q_dct_data[j], len_stream ); + } + else + { + for ( i = 1; i < len_stream; i++ ) + { + q_idx[j + i] = (int16_t) rintf( dct_data[j + i] / step ); + q_dct_data[j + i] = step * q_idx[j + i]; + if ( q_idx[j + i] <= 0 ) + { + q_idx[j + i] = -2 * q_idx[j + i]; + } + else + { + q_idx[j + i] = 2 * q_idx[j + i] - 1; + } + } + } + } + + /* write data */ + nb_bits = 0; + for ( i = 0; i < n_streams; i++ ) + { + nb_bits += write_stream_dct_coeffs_omasa( &q_idx[i * len_stream], len_stream, hMetaData, ( i == 0 ), low_bitrate_mode ); + } + + /* reconstruct masa2total */ + q_dct_data[0] = q_idx[0] * step; + for ( i = 1; i < len_stream; i++ ) + { + if ( ( q_idx[i] % 2 ) == 0 ) + { + q_dct_data[i] = -( q_idx[i] >> 1 ) * step; + } + else + { + q_dct_data[i] = ( ( q_idx[i] + 1 ) >> 1 ) * step; + } + } + + /* inverse DCT2 transform */ + switch ( len_stream ) + { + case 4: + matrix_product( dct4, nblocks, nblocks, 1, q_dct_data, nblocks, 1, 0, dct_data_tmp ); + mvr2r( dct_data_tmp, q_dct_data, nblocks ); + break; + case 5: + matrix_product( dct5, nbands, nbands, 1, q_dct_data, nbands, 1, 0, dct_data_tmp ); + mvr2r( dct_data_tmp, q_dct_data, nbands ); + break; + case 8: + matrix_product( dct8, nbands, nbands, 1, q_dct_data, nbands, 1, 0, dct_data_tmp ); + mvr2r( dct_data_tmp, q_dct_data, nbands ); + break; + case 12: + matrix_product( dct12, nbands, nbands, 1, q_dct_data, nbands, 1, 0, dct_data_tmp ); + mvr2r( dct_data_tmp, q_dct_data, nbands ); + break; + case 20: + matrix_product( dct5, nbands, nbands, 1, q_dct_data, nbands, nblocks, 0, dct_data_tmp ); + matrix_product( dct_data_tmp, nbands, nblocks, 0, dct4, nblocks, nblocks, 0, q_dct_data ); /* reuse of variable*/ + break; + case 32: + matrix_product( dct8, nbands, nbands, 1, q_dct_data, nbands, nblocks, 0, dct_data_tmp ); + matrix_product( dct_data_tmp, nbands, nblocks, 0, dct4, nblocks, nblocks, 0, q_dct_data ); + break; + default: + printf( "Incorrect number of coefficients for OMASA.\n" ); + break; + } + + k = 0; + for ( i = 0; i < nblocks; i++ ) + { + for ( j = 0; j < nbands; j++ ) + { + hQMetaData->masa_to_total_energy_ratio[i][j] = max( 0.0f, q_dct_data[k] ); + hQMetaData->masa_to_total_energy_ratio[i][j] = min( 1.0f, hQMetaData->masa_to_total_energy_ratio[i][j] ); + k++; + } + } + assert( nb_bits == ( hMetaData->nb_bits_tot - bits_pos ) ); + +#ifdef DEBUG_MODE_QMETADATA + { + + fprintf( pF, "frame %d: ", frame ); + fprintf( pF_ratio, "frame %d: ", frame ); + + + /* direction_distance( elevation_orig, azimuth_orig, q_direction, nbands, nblocks, mat_dist );*/ + for ( i = 0; i < nbands; i++ ) + { + for ( j = 0; j < 4; j++ ) + { + fprintf( pF_ratio, " %5.2f ", hQMetaData->masa_to_total_energy_ratio[j][i] ); + } + } + for ( i = 0; i < 20; i++ ) + { + fprintf( pF, " %4d ", q_idx[i] ); + } + fprintf( pF, "\n" ); + fprintf( pF_ratio, "\n" ); + } +#endif + + return; +} +#endif diff --git a/lib_enc/ivas_rom_enc.c b/lib_enc/ivas_rom_enc.c index ce24de702d8382fd4b7d14d8f6d348cc0bd5f891..a031d6df288ee817f891256e8bbb9cd3e1d724d8 100644 --- a/lib_enc/ivas_rom_enc.c +++ b/lib_enc/ivas_rom_enc.c @@ -837,11 +837,13 @@ const HUFF_TABLE huff_beta_table[2] = const int16_t mc_paramupmix_fb_remix_order[4] = {0, 1, 2, 3}; +#ifdef FIX_580_PARAMMC_ENER_BURSTS /*----------------------------------------------------------------------------------* * ParamMC ROM tables *----------------------------------------------------------------------------------*/ const float param_mc_ild_diff_threshold[20] = { 8.0f, 8.0f, 10.0f, 20.0f, 20.0f, 20.0f, 20.0f, 20.0f, 20.0f, 20.0f, 20.0f, 20.0f }; +#endif /* clang-format on */ diff --git a/lib_enc/ivas_rom_enc.h b/lib_enc/ivas_rom_enc.h index fa45706cab5082c87232c012f9ce9fcc36602433..170bf3182035352994fe7e57ae24d55cc84bb24f 100644 --- a/lib_enc/ivas_rom_enc.h +++ b/lib_enc/ivas_rom_enc.h @@ -130,10 +130,12 @@ extern const HUFF_TABLE huff_alpha_table[2]; extern const HUFF_TABLE huff_beta_table[2]; extern const int16_t mc_paramupmix_fb_remix_order[4]; +#ifdef FIX_580_PARAMMC_ENER_BURSTS /*----------------------------------------------------------------------------------* * ParamMC ROM tables *----------------------------------------------------------------------------------*/ extern const float param_mc_ild_diff_threshold[20]; +#endif #endif diff --git a/lib_enc/ivas_sce_enc.c b/lib_enc/ivas_sce_enc.c index b9e6a85527391784ef7c985671cc7e5977fdef93..07ba653dcde494d05ec9f1389fe07860461b3c1f 100644 --- a/lib_enc/ivas_sce_enc.c +++ b/lib_enc/ivas_sce_enc.c @@ -143,7 +143,11 @@ ivas_error ivas_sce_enc( /* set "bits_frame_nominal" */ if ( st_ivas->hQMetaData != NULL && st_ivas->hSpar == NULL ) { +#ifdef MASA_AND_OBJECTS + if ( ( ( st_ivas->mc_mode == MC_MODE_MCMASA ) && ( st_ivas->hEncoderConfig->ivas_total_brate >= MCMASA_SEPARATE_BRATE ) ) || ( st_ivas->ism_mode >= ISM_MASA_MODE_MASA_ONE_OBJ ) ) +#else if ( st_ivas->mc_mode == MC_MODE_MCMASA && st_ivas->hEncoderConfig->ivas_total_brate >= MCMASA_SEPARATE_BRATE ) +#endif { st->bits_frame_nominal = (int16_t) ( hSCE->element_brate / FRAMES_PER_SEC ); } @@ -206,6 +210,19 @@ ivas_error ivas_sce_enc( reset_metadata_spatial( ivas_format, hSCE->hMetaData, hSCE->element_brate, &st->total_brate, st->core_brate, nb_bits_metadata ); +#ifdef MASA_AND_OBJECTS + /*----------------------------------------------------------------* + * Combined format coding: get the ISM importance and the bit-rate + *----------------------------------------------------------------*/ + + if ( ivas_format == MASA_ISM_FORMAT && st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) + { + set_ism_importance_interformat( hSCE->element_brate, 1, st_ivas->hIsmMetaData, st_ivas->hSCE, st_ivas->hMasa->data.lp_noise_CPE, &st_ivas->hIsmMetaData[0]->ism_imp ); + + st->total_brate = ivas_interformat_brate( ISM_MASA_MODE_PARAM_ONE_OBJ, 1, hSCE->element_brate, st_ivas->hIsmMetaData[0]->ism_imp, 0 ) - nb_bits_metadata * FRAMES_PER_SEC; + } +#endif + /*----------------------------------------------------------------* * Write IVAS format signaling in SID frames *----------------------------------------------------------------*/ @@ -224,6 +241,12 @@ ivas_error ivas_sce_enc( { st->flag_ACELP16k = set_ACELP_flag( IVAS_SCE, hSCE->element_brate, st->core_brate, 0, 0, -1, -1 ); } +#ifdef MASA_AND_OBJECTS + else if ( st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ && st->low_rate_mode ) + { + st->flag_ACELP16k = 0; + } +#endif else { st->flag_ACELP16k = set_ACELP_flag( IVAS_SCE, hSCE->element_brate, st->total_brate, 0, 0, -1, -1 ); @@ -337,6 +360,13 @@ ivas_error create_sce_enc( copy_encoder_config( st_ivas, st, 1 ); +#ifdef MASA_AND_OBJECTS + if ( st_ivas->hEncoderConfig->ivas_format == MASA_ISM_FORMAT && ( st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_DISC ) ) + { + st->element_mode = IVAS_SCE; + } +#endif + st->total_brate = hSCE->element_brate; /* dummy initialization for getting right pointers initialization of input buffers in init_coder_ace_plus() */ st->mct_chan_mode = MCT_CHAN_MODE_REGULAR; diff --git a/lib_enc/ivas_spar_md_enc.c b/lib_enc/ivas_spar_md_enc.c index 757f772b13a3a4bf4cc956ea90fdfb598f86ea51..e07f51e86c62ad05e951a95725030fa16fe5ce44 100644 --- a/lib_enc/ivas_spar_md_enc.c +++ b/lib_enc/ivas_spar_md_enc.c @@ -45,7 +45,7 @@ /*------------------------------------------------------------------------------------------* * PreProcessor *------------------------------------------------------------------------------------------*/ -#define IVAS_MAX_MD_BYTES ( 1000 ) +#define IVAS_MAX_MD_BYTES ( 1000 ) // ToDo: not used static const float pr_boost_range[2] = { 0.1f, 0.4f }; diff --git a/lib_enc/ivas_stat_enc.h b/lib_enc/ivas_stat_enc.h index 59abb33a0ad56ce2136fcb9716b4ec5bb5b27788..9e97acc5f238ec79b56a8d63bb1ac63179e241c3 100644 --- a/lib_enc/ivas_stat_enc.h +++ b/lib_enc/ivas_stat_enc.h @@ -729,7 +729,9 @@ typedef struct ivas_param_mc_enc_data_structure int16_t lfe_index; int16_t icc_map_index[PARAM_MC_PARAMETER_FRAMES][PARAM_MC_SZ_ICC_MAP]; int16_t max_param_band_abs_cov; +#ifdef FIX_580_PARAMMC_ENER_BURSTS float prev_ilds[PARAM_MC_MAX_PARAMETER_BANDS][PARAM_MC_SZ_ILD_MAP]; +#endif float ener_fac[PARAM_MC_MAX_PARAMETER_BANDS]; @@ -780,6 +782,16 @@ typedef struct ivas_masa_sync_struct typedef struct ivas_masa_encoder_data_struct { float energy[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; +#ifdef MASA_AND_OBJECTS + float energy_ism[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; /* TODO Nokia: Make an own MASAISM struct for these, and reserve it only for OMASA */ + float energy_ratio_ism[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS]; + float q_energy_ratio_ism[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS]; + int16_t nchan_ism; + float lp_noise_CPE; /* LP filterend total noise estimation */ + int16_t omasa_stereo_sw_cnt; + int16_t omasa_stereo_sw_cnt2; +#endif + int16_t num_Cldfb_instances; HANDLE_CLDFB_FILTER_BANK cldfbAnaEnc[MAX_NUM_ENC_CLDFB_INSTANCES]; int16_t band_mapping[MASA_FREQUENCY_BANDS + 1]; @@ -866,6 +878,46 @@ typedef struct ivas_mcmasa_enc_data_structure } MCMASA_ENC_DATA, *MCMASA_ENC_HANDLE; +#ifdef MASA_AND_OBJECTS +/*----------------------------------------------------------------------------------* + * Object MASA (OMASA) encoder structure + *----------------------------------------------------------------------------------*/ + +typedef struct ivas_omasa_enc_data_structure +{ + uint8_t nbands; + uint8_t nCodingBands; + uint8_t nSubframes; + + /* CLDFB analysis */ + int16_t num_Cldfb_instances; + HANDLE_CLDFB_FILTER_BANK cldfbAnaEnc[MAX_NUM_OBJECTS]; + + /* DirAC parameter estimation */ + float **direction_vector_m[DIRAC_NUM_DIMS]; /* Average direction vector */ + int16_t band_grouping[MASA_FREQUENCY_BANDS + 1]; + int16_t block_grouping[5]; + + /* diffuseness */ + int16_t index_buffer_intensity; + float *buffer_intensity_real[DIRAC_NUM_DIMS][DIRAC_NO_COL_AVG_DIFF]; + float buffer_energy[DIRAC_NO_COL_AVG_DIFF * MASA_FREQUENCY_BANDS]; + + float chnlToFoaMtx[DIRAC_MAX_ANA_CHANS][MCMASA_MAX_ANA_CHANS]; + + float interpolator[L_FRAME48k]; + + float prev_object_dm_gains[MAX_NUM_OBJECTS][MASA_MAX_TRANSPORT_CHANNELS]; + float broadband_energy_sm[MAX_NUM_OBJECTS + MASA_MAX_TRANSPORT_CHANNELS]; + float broadband_energy_prev[MAX_NUM_OBJECTS + MASA_MAX_TRANSPORT_CHANNELS]; + int16_t prev_selected_object; + uint8_t changing_object; + float fade_out_gain[L_FRAME48k]; + float fade_in_gain[L_FRAME48k]; + +} OMASA_ENC_DATA, *OMASA_ENC_HANDLE; +#endif + /*----------------------------------------------------------------------------------* * Stereo CNG handle @@ -934,6 +986,9 @@ typedef struct cpe_enc_data_structure float *input_mem[CPE_CHANNELS]; /* input channels buffers memory; needed to be up-to-date for TD->DFT stereo switching */ +#ifdef MASA_AND_OBJECTS + int32_t brate_surplus; /* bitrate surplus for bitrate adaptation in combined format coding */ +#endif #ifdef DEBUGGING int16_t stereo_mode_cmdl; /* stereo mode forced from the commaand-line */ #endif @@ -1059,6 +1114,9 @@ typedef struct stereo_dmx_evs_enc_data_structure typedef struct ivas_lfe_enc_data_structure { +#ifndef FIX_572_LFE_LPF_ENC + ivas_filters_process_state_t filter_state; +#endif LFE_WINDOW_HANDLE pWindow_state; BSTR_ENC_HANDLE hBstr; /* pointer to encoder bitstream handle */ const uint16_t *cum_freq_models[IVAS_MAX_NUM_QUANT_STRATS][IVAS_MAX_NUM_DCT_COEF_GROUPS]; @@ -1160,8 +1218,13 @@ typedef struct PARAM_MC_ENC_HANDLE hParamMC; /* Parametric MC handle */ MC_PARAMUPMIX_ENC_HANDLE hMCParamUpmix; /* MC Param-Upmix handle */ MCMASA_ENC_HANDLE hMcMasa; /* Multi-channel MASA data handle */ +#ifdef MASA_AND_OBJECTS + OMASA_ENC_HANDLE hOMasa; /* Object-MASA data handle */ +#endif LFE_ENC_HANDLE hLFE; /* LFE data handle */ +#ifdef FIX_572_LFE_LPF_ENC ivas_filters_process_state_t *hLfeLpf; /* low pass filter state for LFE */ +#endif ISM_MODE ism_mode; /* ISM format mode */ MC_MODE mc_mode; /* MC format mode */ diff --git a/lib_enc/ivas_stereo_classifier.c b/lib_enc/ivas_stereo_classifier.c index 555a27d72566c143ff713b6b23a714e8d3b4c4b6..5d672616fc6dbaa31654e16b8340fec07dfe5313 100644 --- a/lib_enc/ivas_stereo_classifier.c +++ b/lib_enc/ivas_stereo_classifier.c @@ -107,8 +107,10 @@ int16_t select_stereo_mode( /* set binary flag indicating LRTD mode based on unclr/xtalk classifiers' decisions */ hStereoClassif->prev_lrtd_mode = hStereoClassif->lrtd_mode; +#ifdef FIX_UNCLR_ISSUE hStereoClassif->unclr_decision = ( hStereoClassif->unclr_decision && hCPE->hCoreCoder[0]->flag_noisy_speech_snr == 0 && hCPE->element_brate > IVAS_16k4 ); +#endif hStereoClassif->lrtd_mode = ( ( hStereoClassif->unclr_decision | hStereoClassif->xtalk_decision ) && is_speech ); stereo_switching_flag = 1; @@ -121,7 +123,11 @@ int16_t select_stereo_mode( stereo_switching_flag = 0; } +#ifdef MASA_AND_OBJECTS + if ( hCPE->element_brate >= MIN_BRATE_MDCT_STEREO && !( hCPE->element_brate == IVAS_48k && ivas_total_brate == IVAS_32k ) ) /* the second condition for PARAM mode OMASA */ +#else if ( hCPE->element_brate >= MIN_BRATE_MDCT_STEREO ) +#endif { hStereoClassif->prev_lrtd_mode = 0; hStereoClassif->lrtd_mode = 0; @@ -208,8 +214,6 @@ int16_t select_stereo_mode( set_f( hStereoClassif->xtalk_fv, -1.0f, SSC_MAX_NFEA ); } } - - #ifdef DEBUG_MODE_TD dbgwrite( &hStereoClassif->unclr_decision, sizeof( int16_t ), 1, L_FRAME16k, "res/unclr_decision.enc" ); dbgwrite( &hStereoClassif->xtalk_decision, sizeof( int16_t ), 1, L_FRAME16k, "res/xtalk_decision.enc" ); diff --git a/lib_enc/ivas_stereo_eclvq_enc.c b/lib_enc/ivas_stereo_eclvq_enc.c index f71beece823e102c87ec95b1943e70956685e1e7..71f0bc805fd910a6fc96fe3994022d08a590d8c2 100644 --- a/lib_enc/ivas_stereo_eclvq_enc.c +++ b/lib_enc/ivas_stereo_eclvq_enc.c @@ -41,7 +41,11 @@ #include "prot.h" #include "wmc_auto.h" /* used only for norm_s in the code_length_from_count function */ +#ifdef FIX_593_STL_INCLUDE #include "stl.h" +#else +#include "basop32.h" +#endif /*--------------------------------------------------------------- diff --git a/lib_enc/ivas_stereo_mdct_core_enc.c b/lib_enc/ivas_stereo_mdct_core_enc.c index 16970d31db8915cdedbca914fab51b691e6ccdfb..2c428726b25379e24a98229305f67c3707098791 100755 --- a/lib_enc/ivas_stereo_mdct_core_enc.c +++ b/lib_enc/ivas_stereo_mdct_core_enc.c @@ -173,6 +173,15 @@ void stereo_mdct_core_enc( sts[0]->hTcxEnc->tfm_mem = sts[1]->hTcxEnc->tfm_mem = sqrtf( 0.5f * ( sts[0]->hTcxEnc->tfm_mem * sts[0]->hTcxEnc->tfm_mem + sts[1]->hTcxEnc->tfm_mem * sts[1]->hTcxEnc->tfm_mem ) ); /* RMS */ sts[0]->hTcxEnc->tcxltp_norm_corr_past = sts[1]->hTcxEnc->tcxltp_norm_corr_past = 0.5f * ( sts[0]->hTcxEnc->tcxltp_norm_corr_past + sts[1]->hTcxEnc->tcxltp_norm_corr_past ); + +#if 0 + if ( sts[0]->bits_frame_channel + sts[1]->bits_frame_channel - meta_bits < 495 ) + { + sts[0]->hTranDet->transientDetector.bIsAttackPresent = 0; + sts[1]->hTranDet->transientDetector.bIsAttackPresent = 0; + } +#endif + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) { st = sts[ch]; @@ -449,7 +458,11 @@ void stereo_mdct_core_enc( sts[ch]->total_brate = ( sts[ch]->bits_frame_channel + sts[ch]->side_bits_frame_channel ) * FRAMES_PER_SEC; } stereo_bits += SMDCT_NBBITS_SPLIT_RATIO; +#ifdef MASA_AND_OBJECTS + assert( ( sts[0]->total_brate + sts[1]->total_brate + ( stereo_bits + signal_bits + meta_bits ) * FRAMES_PER_SEC ) == hCPE->element_brate + hCPE->brate_surplus ); +#else assert( ( sts[0]->total_brate + sts[1]->total_brate + ( stereo_bits + signal_bits + meta_bits ) * FRAMES_PER_SEC ) == hCPE->element_brate ); +#endif assert( hStereoMdct->split_ratio > 0 && hStereoMdct->split_ratio < SMDCT_BITRATE_RATIO_RANGE ); push_next_indice( hBstr, hStereoMdct->split_ratio, SMDCT_NBBITS_SPLIT_RATIO ); diff --git a/lib_enc/ivas_stereo_mdct_stereo_enc.c b/lib_enc/ivas_stereo_mdct_stereo_enc.c index d959cdba2fc5662d6089185b102fbecde893da9b..3d277e241db16735b4eeb38bb577fdcc08bcb7ab 100755 --- a/lib_enc/ivas_stereo_mdct_stereo_enc.c +++ b/lib_enc/ivas_stereo_mdct_stereo_enc.c @@ -1133,15 +1133,29 @@ void initMdctStereoEncData( set_s( hStereoMdct->mdct_stereo_mode, -1, 2 ); /*Initialize sfb parameteres for TCX20 */ +#ifdef FIX_581_CLANG_OFFSET_TO_NULL stereo_mdct_init_bands( tcx_coded_lines, TCX_20_CORE, element_brate, igf, igf ? &hIgfGrid[IGF_GRID_LB_NORM] : NULL, &hStereoMdct->stbParamsTCX20.sfbOffset[0], &hStereoMdct->stbParamsTCX20.sfbCnt ); +#else + stereo_mdct_init_bands( tcx_coded_lines, TCX_20_CORE, element_brate, igf, &hIgfGrid[IGF_GRID_LB_NORM], &hStereoMdct->stbParamsTCX20.sfbOffset[0], &hStereoMdct->stbParamsTCX20.sfbCnt ); +#endif /*Initialize sfb parameteres for TCX10 */ +#ifdef FIX_581_CLANG_OFFSET_TO_NULL stereo_mdct_init_bands( tcx_coded_lines, TCX_10_CORE, element_brate, igf, igf ? &hIgfGrid[IGF_GRID_LB_SHORT] : NULL, &hStereoMdct->stbParamsTCX10.sfbOffset[0], &hStereoMdct->stbParamsTCX10.sfbCnt ); +#else + stereo_mdct_init_bands( tcx_coded_lines, TCX_10_CORE, element_brate, igf, &hIgfGrid[IGF_GRID_LB_SHORT], + &hStereoMdct->stbParamsTCX10.sfbOffset[0], &hStereoMdct->stbParamsTCX10.sfbCnt ); +#endif /*Initialize sfb parameteres for transitions */ +#ifdef FIX_581_CLANG_OFFSET_TO_NULL stereo_mdct_init_bands( tcx_coded_lines, -1, element_brate, igf, igf ? &hIgfGrid[IGF_GRID_LB_TRAN] : NULL, &hStereoMdct->stbParamsTCX20afterACELP.sfbOffset[0], &hStereoMdct->stbParamsTCX20afterACELP.sfbCnt ); +#else + stereo_mdct_init_bands( tcx_coded_lines, -1, element_brate, igf, &hIgfGrid[IGF_GRID_LB_TRAN], + &hStereoMdct->stbParamsTCX20afterACELP.sfbOffset[0], &hStereoMdct->stbParamsTCX20afterACELP.sfbCnt ); +#endif set_s( hStereoMdct->IGFStereoMode, -1, 2 ); diff --git a/lib_enc/ivas_stereo_td_analysis.c b/lib_enc/ivas_stereo_td_analysis.c index d2d72c153426b47d40febe4c2079a100de5f2247..8f86f25986666fc103cc62abed98cce81ce7375f 100644 --- a/lib_enc/ivas_stereo_td_analysis.c +++ b/lib_enc/ivas_stereo_td_analysis.c @@ -111,6 +111,9 @@ static float Comp_diff_lt_corr( CPE_ENC_HANDLE hCPE, const int16_t IsSideMono, c *-------------------------------------------------------------------*/ int16_t stereo_tdm_ener_analysis( +#ifdef MASA_AND_OBJECTS + const int16_t ivas_format, /* i : IVAS format */ +#endif CPE_ENC_HANDLE hCPE, /* i : CPE structure */ const int16_t input_frame, /* i : Number of samples */ int16_t *tdm_SM_or_LRTD_Pri, /* o : channel combination scheme flag in TD stereo OR LRTD primary channel */ @@ -195,6 +198,17 @@ int16_t stereo_tdm_ener_analysis( * of L and R needed to create new mono/side signals *----------------------------------------------------------------*/ +#ifdef MASA_AND_OBJECTS + if ( ivas_format == MASA_ISM_FORMAT ) + { + + if ( ( hCPE->hStereoClassif->lrtd_mode == 1 || hCPE->hStereoTD->prev_fr_LRTD_TD_dec == 1 ) && ( hCPE->element_brate - 50 * FRAMES_PER_SEC + hCPE->brate_surplus + hCPE->brate_surplus < 15000 ) ) + { + hStereoTD->prev_fr_LRTD_TD_dec = 0; + } + } +#endif + rms_thd = RMS_MIN; if ( hCPE->hStereoClassif->lrtd_mode == 1 ) { diff --git a/lib_enc/ivas_stereo_td_enc.c b/lib_enc/ivas_stereo_td_enc.c index a59ac93e49d43a79887e905d9f1fb6f9dfcafa31..858543cf7ee0aa746130dcf986e48e9bd8062b34 100644 --- a/lib_enc/ivas_stereo_td_enc.c +++ b/lib_enc/ivas_stereo_td_enc.c @@ -292,8 +292,8 @@ ivas_error stereo_set_tdm( dbgwrite( &tmp, 2, 1, 320, "res/inst_ratio_L" ); dbgwrite( &ftmp, 4, 1, 320, "res/ratio_L" ); dbgwrite( &tmp, 2, 1, 320, "res/tdm_low_rate_mode" ); - dbgwrite( &tmp, 2, 1, 320, "res/tdm_lp_reuse_flag" ); - dbgwrite( &tmp, 2, 1, 320, "res/mod_ct.enx" ); + // dbgwrite( &tmp, 2, 1, 320, "res/tdm_lp_reuse_flag" ); + // dbgwrite( &tmp, 2, 1, 320, "res/mod_ct.enx" ); } #endif hCPE->hCoreCoder[0]->tdm_LRTD_flag = 0; @@ -311,6 +311,10 @@ ivas_error stereo_set_tdm( *-------------------------------------------------------------------*/ void tdm_configure_enc( +#ifdef MASA_AND_OBJECTS + const int16_t ivas_format, /* i : IVAS format */ + const int16_t ism_mode, /* i : ISM mode in combined format */ +#endif CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */ const float Etot_last[CPE_CHANNELS], /* i/o: Energy of last frame */ const int16_t tdm_SM_or_LRTD_Pri, /* i : channel combination scheme flag in TD stereo OR LRTD primary channel */ @@ -426,6 +430,30 @@ void tdm_configure_enc( sts[1]->coder_type = GENERIC; } +#ifdef MASA_AND_OBJECTS + if ( hCPE->element_brate - nb_bits_metadata * FRAMES_PER_SEC + hCPE->brate_surplus < 12000 ) + { + if ( sts[1]->coder_type == UNVOICED ) + { + sts[1]->coder_type = GENERIC; + } + hStereoTD->tdm_lp_reuse_flag = 1; + + if ( hCPE->element_brate - nb_bits_metadata * FRAMES_PER_SEC + hCPE->brate_surplus < 11000 ) + { + sts[1]->coder_type = INACTIVE; + } + } + + if ( hCPE->element_brate - nb_bits_metadata * FRAMES_PER_SEC + hCPE->brate_surplus < 14700 ) + { + if ( sts[0]->coder_type == TRANSITION ) + { + sts[0]->coder_type = GENERIC; + } + } +#endif + mod_ct = AUDIO; if ( hCPE->element_brate < IVAS_24k4 ) { @@ -459,7 +487,16 @@ void tdm_configure_enc( * bitbudget distribution between channels (taking into account also metadata bitbudget) *----------------------------------------------------------------*/ +#ifdef MASA_AND_OBJECTS + tdm_bit_alloc( ivas_format, + ism_mode, + hCPE->element_brate - nb_bits_metadata * FRAMES_PER_SEC + hCPE->brate_surplus, + hStereoTD->tdm_lp_reuse_flag, &( sts[0]->total_brate ), &( sts[1]->total_brate ), + &( hStereoTD->tdm_low_rate_mode ), sts[1]->coder_type, tdm_ratio_bit_alloc_idx, hStereoTD->tdm_Pitch_reuse_flag, + sts[0]->bwidth, sts[1]->bwidth, sts[0]->flag_ACELP16k, hStereoTD->tdm_LRTD_flag, mod_ct, hStereoTD->tdm_inst_ratio_idx ); +#else tdm_bit_alloc( hCPE->element_brate - nb_bits_metadata * FRAMES_PER_SEC, hStereoTD->tdm_lp_reuse_flag, &( sts[0]->total_brate ), &( sts[1]->total_brate ), &( hStereoTD->tdm_low_rate_mode ), sts[1]->coder_type, tdm_ratio_bit_alloc_idx, hStereoTD->tdm_Pitch_reuse_flag, sts[0]->bwidth, sts[1]->bwidth, sts[0]->flag_ACELP16k, hStereoTD->tdm_LRTD_flag, mod_ct, hStereoTD->tdm_inst_ratio_idx ); +#endif if ( sts[0]->GSC_IVAS_mode > 0 && sts[0]->total_brate <= STEREO_GSC_BIT_RATE_ALLOC ) { @@ -522,9 +559,9 @@ void tdm_configure_enc( } #ifdef DEBUG_MODE_TD - dbgwrite( &hStereoTD->tdm_low_rate_mode, 2, 1, 320, "res/tdm_low_rate_mode" ); - dbgwrite( &hStereoTD->tdm_lp_reuse_flag, 2, 1, 320, "res/tdm_lp_reuse_flag" ); - dbgwrite( &mod_ct, 2, 1, 320, "res/mod_ct.enx" ); + dbgwrite( &hStereoTD->tdm_low_rate_mode, 2, 1, 320, "res/tdm_low_rate_mode_c" ); + dbgwrite( &hStereoTD->tdm_lp_reuse_flag, 2, 1, 320, "res/tdm_lp_reuse_flag_c" ); + dbgwrite( &mod_ct, 2, 1, 320, "res/mod_ct.enc" ); #endif /*----------------------------------------------------------------* @@ -831,4 +868,6 @@ void stereo_tdm_prep_dwnmx( } } } + + return; } diff --git a/lib_enc/lib_enc.c b/lib_enc/lib_enc.c index 5e051e41b7eb10875e4f5c57d04e20810e9b4045..83f5e68ee829c02ec2f21d86e1deb5a130869fe3 100644 --- a/lib_enc/lib_enc.c +++ b/lib_enc/lib_enc.c @@ -330,6 +330,63 @@ ivas_error IVAS_ENC_ConfigureForStereo( } +#ifdef MASA_AND_OBJECTS +/*---------------------------------------------------------------------* + * IVAS_ENC_ConfigureForMASAObjects() + * + * Configure and initialize the combined MASA and ISM encoder. + *---------------------------------------------------------------------*/ + +ivas_error IVAS_ENC_ConfigureForMASAObjects( + IVAS_ENC_HANDLE hIvasEnc, /* i/o: IVAS encoder handle */ + const int32_t inputFs, /* i : input sampling frequency */ + const int32_t bitrate, /* i : requested bitrate of the ouput bitstream */ + const IVAS_ENC_BANDWIDTH maxBandwidth, /* i : bandwidth limitation */ + const IVAS_ENC_DTX_CONFIG dtxConfig, /* i : configuration of DTX, can by set to default by using IVAS_ENC_GetDefaultDtxConfig() */ + const uint16_t numObjects, /* i : number of objects to be encoded */ + const int16_t masaVariant /* i : index specifying the number of MASA transport channels */ +) +{ + Encoder_Struct *st_ivas; + ivas_error error; + + if ( ( error = doCommonConfigureChecks( hIvasEnc ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( numObjects > MAX_NUM_OBJECTS ) + { + return IVAS_ERR_TOO_MANY_INPUTS; + } + st_ivas = hIvasEnc->st_ivas; + switch ( masaVariant ) + { + case IVAS_ENC_MASA_2CH: + st_ivas->hEncoderConfig->nchan_inp = CPE_CHANNELS + numObjects; + st_ivas->hEncoderConfig->element_mode_init = IVAS_CPE_DFT; /* initialization only, might be changed later based on element_brate */ + break; + case IVAS_ENC_MASA_1CH: + st_ivas->hEncoderConfig->nchan_inp = 1 + numObjects; + st_ivas->hEncoderConfig->element_mode_init = IVAS_CPE_DFT; /* initialization only, might be changed later based on element_brate */ + break; + default: + return IVAS_ERR_INVALID_MASA_CONFIG; + break; + } + + st_ivas = hIvasEnc->st_ivas; + + /* Currently this is true but it is already shown in descriptive metadata that there can be inequality for this. */ + st_ivas->nchan_transport = st_ivas->hEncoderConfig->nchan_inp - numObjects; + st_ivas->hEncoderConfig->ivas_format = MASA_ISM_FORMAT; + st_ivas->hEncoderConfig->nchan_ism = numObjects; + + return configureEncoder( hIvasEnc, inputFs, bitrate, maxBandwidth, dtxConfig, IVAS_ENC_GetDefaultChannelAwareConfig() ); +} +#endif + + /*---------------------------------------------------------------------* * IVAS_ENC_ConfigureForObjects() * @@ -396,7 +453,11 @@ ivas_error IVAS_ENC_FeedObjectMetadata( return IVAS_ERR_NOT_CONFIGURED; } +#ifdef MASA_AND_OBJECTS + if ( hIvasEnc->st_ivas->hEncoderConfig->ivas_format != ISM_FORMAT && hIvasEnc->st_ivas->hEncoderConfig->ivas_format != MASA_ISM_FORMAT ) +#else if ( hIvasEnc->st_ivas->hEncoderConfig->ivas_format != ISM_FORMAT ) +#endif { return IVAS_ERR_METADATA_NOT_EXPECTED; } @@ -553,7 +614,11 @@ ivas_error IVAS_ENC_FeedMasaMetadata( return IVAS_ERR_NOT_CONFIGURED; } +#ifdef MASA_AND_OBJECTS + if ( hIvasEnc->st_ivas->hEncoderConfig->ivas_format != MASA_FORMAT && hIvasEnc->st_ivas->hEncoderConfig->ivas_format != MASA_ISM_FORMAT ) +#else if ( hIvasEnc->st_ivas->hEncoderConfig->ivas_format != MASA_FORMAT ) +#endif { return IVAS_ERR_METADATA_NOT_EXPECTED; } @@ -640,6 +705,9 @@ static ivas_error configureEncoder( Encoder_Struct *st_ivas; ENCODER_CONFIG_HANDLE hEncoderConfig; ivas_error error; +#ifdef MASA_AND_OBJECTS + int32_t cpe_brate; +#endif error = IVAS_ERR_OK; @@ -781,6 +849,23 @@ static ivas_error configureEncoder( } } } +#ifdef MASA_AND_OBJECTS + else if ( hEncoderConfig->ivas_format == MASA_ISM_FORMAT ) + { + st_ivas->ism_mode = ivas_omasa_ism_mode_select( st_ivas->hEncoderConfig->ivas_total_brate, hEncoderConfig->nchan_ism ); + + cpe_brate = calculate_cpe_brate_MASA_ISM( st_ivas->ism_mode, st_ivas->hEncoderConfig->ivas_total_brate, hEncoderConfig->nchan_ism ); + + /*adapt element_mode according to the bit-rate*/ + if ( hEncoderConfig->element_mode_init != IVAS_SCE ) + { + if ( cpe_brate >= IVAS_48k ) + { + hEncoderConfig->element_mode_init = IVAS_CPE_MDCT; + } + } + } +#endif } else /* EVS mono */ { @@ -1580,6 +1665,12 @@ static ivas_error printConfigInfo_enc( fprintf( stdout, "IVAS mode: Multi-Channel 7.1+4\n" ); } } +#ifdef MASA_AND_OBJECTS + else if ( hEncoderConfig->ivas_format == MASA_ISM_FORMAT ) + { + fprintf( stdout, "IVAS format: combined ISM and MASA (%i ISM stream(s))\n", hEncoderConfig->nchan_inp - 2 ); + } +#endif if ( hEncoderConfig->is_binaural ) { @@ -1649,11 +1740,13 @@ static ivas_error printConfigInfo_enc( { if ( newBandwidthApi != hEncoderConfig->max_bwidth ) { +#ifdef ISM_FB if ( hEncoderConfig->ivas_format == ISM_FORMAT ) { fprintf( stdout, "\nFB coding not supported below %.2f kbps for %i objects. Switching to SWB.\n", hEncoderConfig->nchan_ism * MIN_BRATE_FB_ISM / 1000.f, hEncoderConfig->nchan_ism ); } else +#endif { fprintf( stdout, "\nFB coding not supported below %.2f kbps. Switching to SWB.\n", MIN_BRATE_FB_STEREO / 1000.f ); } @@ -1953,8 +2046,12 @@ static ivas_error sanitizeBandwidth( } else { +#ifdef ISM_FB if ( max_bwidth_tmp == FB && ( ( hEncoderConfig->ivas_format != ISM_FORMAT && hEncoderConfig->ivas_total_brate < MIN_BRATE_FB_STEREO ) || ( hEncoderConfig->ivas_format == ISM_FORMAT && hEncoderConfig->ivas_total_brate / hEncoderConfig->nchan_ism < MIN_BRATE_FB_ISM ) ) ) +#else + if ( max_bwidth_tmp == FB && hEncoderConfig->ivas_total_brate < MIN_BRATE_FB_STEREO ) +#endif { max_bwidth_tmp = SWB; } diff --git a/lib_enc/lib_enc.h b/lib_enc/lib_enc.h index 9d2578755799653924c3cddb6e5b8d8f176732f5..8c015a99e4c6a74c448d525e589a6a633d316da9 100644 --- a/lib_enc/lib_enc.h +++ b/lib_enc/lib_enc.h @@ -50,6 +50,9 @@ typedef enum _IVAS_ENC_INPUT_FORMAT IVAS_ENC_INPUT_SBA, IVAS_ENC_INPUT_MASA, IVAS_ENC_INPUT_MC, +#ifdef MASA_AND_OBJECTS + IVAS_ENC_INPUT_MASA_ISM, +#endif IVAS_DEC_INPUT_UNKNOWN = 0xffff } IVAS_ENC_INPUT_FORMAT; @@ -101,6 +104,14 @@ typedef enum _IVAS_ENC_COMPLEXITY_LEVEL IVAS_ENC_COMPLEXITY_LEVEL_THREE = 3 } IVAS_ENC_COMPLEXITY_LEVEL; +#ifdef MASA_AND_OBJECTS +typedef enum _IVAS_ENC_COMBINED_FORMAT +{ + IVAS_ENC_MASA_ISM = 1, + IVAS_ENC_COMBINED_UNDEFINED = 0xffff +} IVAS_ENC_COMBINED_FORMAT; +#endif + #ifdef DEBUGGING typedef enum _IVAS_ENC_STEREO_MODE { @@ -193,6 +204,19 @@ ivas_error IVAS_ENC_ConfigureForObjects( const bool ism_extended_metadata /* i : Extended metadata used (true/false), where extended metadata includes radius and orientation */ ); +#ifdef MASA_AND_OBJECTS +/*! r: encoder error code */ +ivas_error IVAS_ENC_ConfigureForMASAObjects( + IVAS_ENC_HANDLE hIvasEnc, /* i/o: IVAS encoder handle */ + const int32_t inputFs, /* i : input sampling frequency */ + const int32_t bitrate, /* i : requested bitrate of the ouput bitstream */ + const IVAS_ENC_BANDWIDTH maxBandwidth, /* i : bandwidth limitation */ + const IVAS_ENC_DTX_CONFIG dtxConfig, /* i : configuration of DTX, can by set to default by using IVAS_ENC_GetDefaultDtxConfig() */ + const uint16_t numObjects, /* i : number of objects to be encoded */ + const int16_t masaVariant /* i : index specifying the number of MASA transport channels */ +); +#endif + /*! r: error code */ ivas_error IVAS_ENC_ConfigureForAmbisonics( IVAS_ENC_HANDLE hIvasEnc, /* i/o: IVAS encoder handle */ diff --git a/lib_enc/stat_enc.h b/lib_enc/stat_enc.h index 34efc3da7f3d9ae45da4015427257f4b4217bddc..45d01ac6cac73baec5e74780732cfa05ce469c6a 100644 --- a/lib_enc/stat_enc.h +++ b/lib_enc/stat_enc.h @@ -126,7 +126,11 @@ typedef struct float firState1; float firState2; +#ifdef FIX_583_CLANG_TRANS_DET uint16_t ramp_up_flag; /* bit map flags to indicate a ramp up in beginning of TCX frame */ +#else + int16_t ramp_up_flag; /* bit map flags to indicate a ramp up in beginning of TCX frame */ +#endif } SubblockEnergies; diff --git a/lib_enc/transient_detection.c b/lib_enc/transient_detection.c index 04cf8ea2471a095aede392c3f01641dce49b3c15..3b345b733396d022a2eae591fef15730b7a09238 100644 --- a/lib_enc/transient_detection.c +++ b/lib_enc/transient_detection.c @@ -241,7 +241,11 @@ void RunTransientDetection( UpdateDelayBuffer( filteredInput, length, &hTranDet->delayBuffer ); /* compute ramp up flag */ +#ifdef FIX_583_CLANG_TRANS_DET pSubblockEnergies->ramp_up_flag = ( ( pSubblockEnergies->ramp_up_flag << 1 ) & 0x0003 ); +#else + pSubblockEnergies->ramp_up_flag = pSubblockEnergies->ramp_up_flag << 1; +#endif e0 = dotp( filteredInput + length / 2, filteredInput + length / 2, pSubblockEnergies->pDelayBuffer->nSubblockSize / 2 ) + 0.5f * MIN_BLOCK_ENERGY; e1 = pSubblockEnergies->subblockNrg[pSubblockEnergies->nDelay + 4] - e0; if ( e1 > e0 ) diff --git a/lib_rend/ivas_dirac_dec_binaural_functions.c b/lib_rend/ivas_dirac_dec_binaural_functions.c index 8a3f33b80b1949416653dfb99e889414c3e22b6d..5ca721b331f4f5e518dcb5a7c6ca6536c5cac8c0 100644 --- a/lib_rend/ivas_dirac_dec_binaural_functions.c +++ b/lib_rend/ivas_dirac_dec_binaural_functions.c @@ -56,6 +56,10 @@ #define IVAS_TDET_DUCK_MULT_FAC_PARA_BIN ( 2.0f ) #define IVAS_TDET_DUCK_MULT_FAC_PARA_BIN_LOW_BR ( 3.0f ) +#ifdef MASA_AND_OBJECTS +#define STEREO_PREPROCESS_IIR_FACTOR ( 0.9f ) +#endif + /* powf(0.95f, 4.0f) for sub-frame smoothing instead of CLDFB slot */ #define ADAPT_HTPROTO_IIR_FAC 0.81450625f @@ -64,7 +68,11 @@ #define ADAPT_HTPROTO_ROT_LIM_0 0.4f #define ADAPT_HTPROTO_ROT_LIM_1 0.8f +#ifdef MASA_AND_OBJECTS +#define MAX_GAIN_CACHE_SIZE ( ( MASA_MAXIMUM_DIRECTIONS * 3 ) + MAX_NUM_OBJECTS ) /* == different calls to get gains */ +#else #define MAX_GAIN_CACHE_SIZE 6 +#endif typedef struct hrtfGainCache { @@ -74,18 +82,6 @@ typedef struct hrtfGainCache float shVec[HRTF_SH_CHANNELS]; } PARAMBIN_HRTF_GAIN_CACHE; -typedef struct parambin_rend_config_data -{ - int16_t separateCenterChannelRendering; - IVAS_FORMAT ivas_format; - MC_MODE mc_mode; - int32_t ivas_total_brate; - int16_t nchan_transport; - float qualityBasedSmFactor; - int16_t processReverb; - -} PARAMBIN_REND_CONFIG, *PARAMBIN_REND_CONFIG_HANDLE; - /*------------------------------------------------------------------------- * Local function prototypes @@ -93,13 +89,13 @@ typedef struct parambin_rend_config_data static void ivas_dirac_dec_binaural_internal( Decoder_Struct *st_ivas, COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, float *output_f[], const int16_t nchan_transport, const int16_t subframe ); -static void ivas_dirac_dec_decorrelate_slot( DIRAC_DEC_BIN_HANDLE hDiracDecBin, const int16_t num_freq_bands, const int16_t slot, float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float decRe[][CLDFB_NO_CHANNELS_MAX], float decIm[][CLDFB_NO_CHANNELS_MAX] ); +static void ivas_dirac_dec_decorrelate_slot( DIRAC_DEC_HANDLE hDirAC, const int16_t slot, float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float decRe[][CLDFB_NO_CHANNELS_MAX], float decIm[][CLDFB_NO_CHANNELS_MAX] ); -static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matrices( DIRAC_DEC_BIN_HANDLE hDiracDecBin, SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, PARAMBIN_REND_CONFIG_HANDLE hConfig, float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float Rmat[3][3], const int16_t subframe, const int16_t isHeadtracked ); +static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matrices( Decoder_Struct *st_ivas, float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float Rmat[3][3], const int16_t subframe, const int16_t isHeadtracked ); -static void ivas_dirac_dec_binaural_determine_processing_matrices( DIRAC_DEC_BIN_HANDLE hDiracDecBin, SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, PARAMBIN_REND_CONFIG_HANDLE hConfig, const int16_t max_band_decorr, float Rmat[3][3], const int16_t isHeadtracked ); +static void ivas_dirac_dec_binaural_determine_processing_matrices( Decoder_Struct *st_ivas, const int16_t max_band_decorr, float Rmat[3][3], const int16_t isHeadtracked ); -static void ivas_dirac_dec_binaural_process_output( DIRAC_DEC_BIN_HANDLE hDiracDecBin, SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, HANDLE_CLDFB_FILTER_BANK cldfbSynDec[MAX_OUTPUT_CHANNELS], float *output_f[], float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], const int16_t max_band_decorr, const int16_t numInChannels, const int16_t processReverb, const int16_t subframe ); +static void ivas_dirac_dec_binaural_process_output( Decoder_Struct *st_ivas, float *output_f[], float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], const int16_t max_band_decorr, const int16_t numInChannels, const int16_t subframe ); static void adaptTransportSignalsHeadtracked( COMBINED_ORIENTATION_HANDLE hHeadTrackData, float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], const int16_t nBins, const int16_t nSlots, float Rmat[3][3] ); @@ -116,69 +112,67 @@ static void matrixMul( float Are[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float Ai static void matrixTransp2Mul( float Are[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float Aim[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float Bre[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float Bim[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float outRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float outIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS] ); -// Todo Tapani refactor: Create separate init & render functions for MASA external renderer. The decoder versions would become too complex if generalized. - /*------------------------------------------------------------------------- * ivas_dirac_dec_init_binaural_data() * * Initialize parametric binaural renderer *------------------------------------------------------------------------*/ -// Todo Tapani refactor: To be moved to lib_dec ivas_error ivas_dirac_dec_init_binaural_data( Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ HRTFS_PARAMBIN_HANDLE hHrtfParambin /* i : HRTF structure for rendering */ ) { - DIRAC_DEC_BIN_HANDLE hDiracDecBin; + DIRAC_DEC_BIN_HANDLE hBinaural; int16_t nBins; int32_t output_Fs; RENDERER_TYPE renderer_type; int16_t j, k, bin; float binCenterFreq, tmpFloat; ivas_error error; - float frequency_axis[CLDFB_NO_CHANNELS_MAX]; - hDiracDecBin = st_ivas->hDiracDecBin; + hBinaural = st_ivas->hDiracDecBin; - if ( hDiracDecBin == NULL ) + if ( hBinaural == NULL ) { - if ( ( hDiracDecBin = (DIRAC_DEC_BIN_HANDLE) malloc( sizeof( DIRAC_DEC_BIN_DATA ) ) ) == NULL ) + if ( ( hBinaural = (DIRAC_DEC_BIN_HANDLE) malloc( sizeof( DIRAC_DEC_BIN_DATA ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC binaural handle " ); } - hDiracDecBin->hTdDecorr = NULL; - hDiracDecBin->hReverb = NULL; - hDiracDecBin->h_freq_domain_decorr_ap_params = NULL; - hDiracDecBin->h_freq_domain_decorr_ap_state = NULL; + hBinaural->hTdDecorr = NULL; + hBinaural->hReverb = NULL; } + nBins = st_ivas->hDirAC->num_freq_bands; output_Fs = st_ivas->hDecoderConfig->output_Fs; - nBins = st_ivas->hSpatParamRendCom->num_freq_bands; renderer_type = st_ivas->renderer_type; for ( j = 0; j < BINAURAL_CHANNELS; j++ ) { +#ifdef MASA_AND_OBJECTS + for ( k = 0; k < BINAURAL_CHANNELS + MAX_NUM_OBJECTS; k++ ) +#else for ( k = 0; k < BINAURAL_CHANNELS + 1; k++ ) +#endif { - set_zero( hDiracDecBin->processMtxRe[j][k], nBins ); - set_zero( hDiracDecBin->processMtxIm[j][k], nBins ); + set_zero( hBinaural->processMtxRe[j][k], nBins ); + set_zero( hBinaural->processMtxIm[j][k], nBins ); } for ( k = 0; k < BINAURAL_CHANNELS; k++ ) { - set_zero( hDiracDecBin->processMtxDecRe[j][k], nBins ); - set_zero( hDiracDecBin->processMtxDecIm[j][k], nBins ); + set_zero( hBinaural->processMtxDecRe[j][k], nBins ); + set_zero( hBinaural->processMtxDecIm[j][k], nBins ); } - set_zero( hDiracDecBin->ChEnePrev[j], nBins ); - set_zero( hDiracDecBin->ChEneOutPrev[j], nBins ); + set_zero( hBinaural->ChEnePrev[j], nBins ); + set_zero( hBinaural->ChEneOutPrev[j], nBins ); } - set_zero( hDiracDecBin->ChCrossRePrev, nBins ); - set_zero( hDiracDecBin->ChCrossImPrev, nBins ); - set_zero( hDiracDecBin->ChCrossReOutPrev, nBins ); - set_zero( hDiracDecBin->ChCrossImOutPrev, nBins ); - hDiracDecBin->renderStereoOutputInsteadOfBinaural = 0; + set_zero( hBinaural->ChCrossRePrev, nBins ); + set_zero( hBinaural->ChCrossImPrev, nBins ); + set_zero( hBinaural->ChCrossReOutPrev, nBins ); + set_zero( hBinaural->ChCrossImOutPrev, nBins ); + hBinaural->renderStereoOutputInsteadOfBinaural = 0; for ( bin = 0; bin < nBins; bin++ ) @@ -186,35 +180,35 @@ ivas_error ivas_dirac_dec_init_binaural_data( binCenterFreq = ( (float) bin + CLDFB_HALF_BIN_FREQUENCY_OFFSET ) / (float) nBins * ( (float) output_Fs / 2.0f ); /* These formulas and values are from Christian Borss's publication for binaural diffuse field coherence */ tmpFloat = max( 0.0f, 1.0f - binCenterFreq / 2700.0f ); - hDiracDecBin->diffuseFieldCoherence[bin] = tmpFloat * sinf( binCenterFreq * EVS_PI / 550.0f ) / ( binCenterFreq * EVS_PI / 550.0f ); + hBinaural->diffuseFieldCoherence[bin] = tmpFloat * sinf( binCenterFreq * EVS_PI / 550.0f ) / ( binCenterFreq * EVS_PI / 550.0f ); } for ( bin = 0; bin < BINAURAL_COHERENCE_DIFFERENCE_BINS; bin++ ) { - hDiracDecBin->diffuseFieldCoherenceX[bin] = hDiracDecBin->diffuseFieldCoherence[bin] + diffuseFieldCoherenceDifferenceX[bin]; - hDiracDecBin->diffuseFieldCoherenceY[bin] = hDiracDecBin->diffuseFieldCoherence[bin] + diffuseFieldCoherenceDifferenceY[bin]; - hDiracDecBin->diffuseFieldCoherenceZ[bin] = hDiracDecBin->diffuseFieldCoherence[bin] + diffuseFieldCoherenceDifferenceZ[bin]; + hBinaural->diffuseFieldCoherenceX[bin] = hBinaural->diffuseFieldCoherence[bin] + diffuseFieldCoherenceDifferenceX[bin]; + hBinaural->diffuseFieldCoherenceY[bin] = hBinaural->diffuseFieldCoherence[bin] + diffuseFieldCoherenceDifferenceY[bin]; + hBinaural->diffuseFieldCoherenceZ[bin] = hBinaural->diffuseFieldCoherence[bin] + diffuseFieldCoherenceDifferenceZ[bin]; } if ( renderer_type == RENDERER_BINAURAL_PARAMETRIC ) /* Indication of binaural rendering without room effect */ { - set_f( hDiracDecBin->earlyPartEneCorrection, 1.0f, CLDFB_NO_CHANNELS_MAX ); - hDiracDecBin->hReverb = NULL; + set_f( hBinaural->earlyPartEneCorrection, 1.0f, CLDFB_NO_CHANNELS_MAX ); + hBinaural->hReverb = NULL; } else if ( renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) /* Indication of binaural rendering with room effect */ { - mvr2r( hHrtfParambin->parametricEarlyPartEneCorrection, hDiracDecBin->earlyPartEneCorrection, nBins ); + mvr2r( hHrtfParambin->parametricEarlyPartEneCorrection, hBinaural->earlyPartEneCorrection, nBins ); /* reconfiguration needed when Reverb. parameters are changed -> close and open the handle again */ - if ( hDiracDecBin->hReverb != NULL && ( ( hDiracDecBin->hReverb->numBins != nBins ) || - ( hDiracDecBin->hReverb->blockSize != CLDFB_SLOTS_PER_SUBFRAME ) ) ) + if ( hBinaural->hReverb != NULL && ( ( hBinaural->hReverb->numBins != nBins ) || + ( hBinaural->hReverb->blockSize != CLDFB_SLOTS_PER_SUBFRAME ) ) ) { - ivas_binaural_reverb_close( &( hDiracDecBin->hReverb ) ); + ivas_binaural_reverb_close( &( hBinaural->hReverb ) ); } - if ( hDiracDecBin->hReverb == NULL ) + if ( hBinaural->hReverb == NULL ) { - if ( ( error = ivas_binaural_reverb_open( &hDiracDecBin->hReverb, + if ( ( error = ivas_binaural_reverb_open( &hBinaural->hReverb, nBins, CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES, NULL, st_ivas->hIntSetup.output_config, @@ -229,52 +223,28 @@ ivas_error ivas_dirac_dec_init_binaural_data( } else if ( renderer_type == RENDERER_STEREO_PARAMETRIC ) { - set_f( hDiracDecBin->earlyPartEneCorrection, 1.0f, CLDFB_NO_CHANNELS_MAX ); - hDiracDecBin->hReverb = NULL; - hDiracDecBin->renderStereoOutputInsteadOfBinaural = 1; + set_f( hBinaural->earlyPartEneCorrection, 1.0f, CLDFB_NO_CHANNELS_MAX ); + hBinaural->hReverb = NULL; + hBinaural->renderStereoOutputInsteadOfBinaural = 1; } else /* Not valid renderer type for this renderer */ { assert( false ); } - hDiracDecBin->hDiffuseDist = NULL; /* Memory is allocated from stack during runtime when needed */ - - if ( hDiracDecBin->hTdDecorr == NULL ) + if ( hBinaural->hTdDecorr == NULL ) { - hDiracDecBin->useTdDecorr = 0; + hBinaural->useTdDecorr = 0; } - if ( hDiracDecBin->h_freq_domain_decorr_ap_params != NULL ) - { - ivas_dirac_dec_decorr_close( &hDiracDecBin->h_freq_domain_decorr_ap_params, &hDiracDecBin->h_freq_domain_decorr_ap_state ); - } - - if ( ( error = ivas_td_decorr_reconfig_dec( st_ivas->ivas_format, st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->nchan_transport, st_ivas->hDecoderConfig->output_Fs, &( hDiracDecBin->hTdDecorr ), &( hDiracDecBin->useTdDecorr ) ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_td_decorr_reconfig_dec( st_ivas->ivas_format, st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->nchan_transport, st_ivas->hDecoderConfig->output_Fs, &( hBinaural->hTdDecorr ), &( hBinaural->useTdDecorr ) ) ) != IVAS_ERR_OK ) { return error; } - if ( !hDiracDecBin->useTdDecorr && !( st_ivas->ivas_format == ISM_FORMAT && st_ivas->ism_mode == ISM_MODE_PARAM ) ) - { - ivas_dirac_dec_get_frequency_axis( frequency_axis, output_Fs, nBins ); - if ( ( error = ivas_dirac_dec_decorr_open( &( hDiracDecBin->h_freq_domain_decorr_ap_params ), - &( hDiracDecBin->h_freq_domain_decorr_ap_state ), - nBins, - BINAURAL_CHANNELS, - BINAURAL_CHANNELS, - DIRAC_SYNTHESIS_PSD_LS, - frequency_axis, - BINAURAL_CHANNELS, - output_Fs ) ) != IVAS_ERR_OK ) - { - return error; - } - } - - hDiracDecBin->reqularizationFactor = configure_reqularization_factor( st_ivas->ivas_format, st_ivas->hDecoderConfig->ivas_total_brate ); + hBinaural->reqularizationFactor = configure_reqularization_factor( st_ivas->ivas_format, st_ivas->hDecoderConfig->ivas_total_brate ); - st_ivas->hDiracDecBin = hDiracDecBin; + st_ivas->hDiracDecBin = hBinaural; /* allocate transport channels*/ if ( st_ivas->hDecoderConfig->voip_active == 1 && st_ivas->hTcBuffer == NULL ) @@ -313,10 +283,6 @@ void ivas_dirac_dec_close_binaural_data( } ivas_td_decorr_dec_close( &( ( *hBinaural )->hTdDecorr ) ); - if ( ( *hBinaural )->h_freq_domain_decorr_ap_params != NULL ) - { - ivas_dirac_dec_decorr_close( &( *hBinaural )->h_freq_domain_decorr_ap_params, &( *hBinaural )->h_freq_domain_decorr_ap_state ); - } free( *hBinaural ); *hBinaural = NULL; @@ -377,7 +343,6 @@ ivas_error ivas_dirac_dec_binaural_copy_hrtfs( * *------------------------------------------------------------------------*/ -// Todo Tapani refactor: To be moved to lib_dec void ivas_dirac_dec_binaural_render( Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ const uint16_t nSamplesAsked, /* i : number of CLDFB slots requested */ @@ -390,13 +355,13 @@ void ivas_dirac_dec_binaural_render( int16_t slots_to_render, first_sf, last_sf, subframe_idx; uint16_t slot_size, ch; uint16_t nchan_out; - SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom; + DIRAC_DEC_HANDLE hDirAC; float *output_f_local[MAX_OUTPUT_CHANNELS]; - hSpatParamRendCom = st_ivas->hSpatParamRendCom; + hDirAC = st_ivas->hDirAC; nchan_out = BINAURAL_CHANNELS; #ifdef DEBUGGING - assert( hSpatParamRendCom ); + assert( hDirAC ); #endif for ( ch = 0; ch < nchan_out; ch++ ) { @@ -405,14 +370,14 @@ void ivas_dirac_dec_binaural_render( slot_size = NS2SA( st_ivas->hDecoderConfig->output_Fs, CLDFB_SLOT_NS ); /* loop for synthesis, assume we always have to render in multiples of 5ms subframes with spills */ - slots_to_render = min( hSpatParamRendCom->num_slots - hSpatParamRendCom->slots_rendered, nSamplesAsked / slot_size ); + slots_to_render = min( hDirAC->num_slots - hDirAC->slots_rendered, nSamplesAsked / slot_size ); *nSamplesRendered = slots_to_render * slot_size; - first_sf = hSpatParamRendCom->subframes_rendered; + first_sf = hDirAC->subframes_rendered; last_sf = first_sf; while ( slots_to_render > 0 ) { - slots_to_render -= hSpatParamRendCom->subframe_nbslots[last_sf]; + slots_to_render -= hDirAC->subframe_nbslots[last_sf]; last_sf++; } @@ -421,7 +386,7 @@ void ivas_dirac_dec_binaural_render( #endif for ( subframe_idx = first_sf; subframe_idx < last_sf; subframe_idx++ ) { - int16_t n_samples_sf = slot_size * hSpatParamRendCom->subframe_nbslots[subframe_idx]; + int16_t n_samples_sf = slot_size * hDirAC->subframe_nbslots[subframe_idx]; ivas_dirac_dec_binaural_internal( st_ivas, st_ivas->hCombinedOrientationData, output_f_local, nchan_transport, subframe_idx ); for ( ch = 0; ch < nchan_out; ch++ ) { @@ -429,12 +394,12 @@ void ivas_dirac_dec_binaural_render( } } - if ( hSpatParamRendCom->slots_rendered == hSpatParamRendCom->num_slots ) + if ( hDirAC->slots_rendered == hDirAC->num_slots ) { - hSpatParamRendCom->dirac_read_idx = ( hSpatParamRendCom->dirac_read_idx + DEFAULT_JBM_SUBFRAMES_5MS ) % hSpatParamRendCom->dirac_md_buffer_length; + st_ivas->hDirAC->dirac_read_idx = ( st_ivas->hDirAC->dirac_read_idx + DEFAULT_JBM_SUBFRAMES_5MS ) % st_ivas->hDirAC->dirac_md_buffer_length; } - *nSamplesAvailable = ( hSpatParamRendCom->num_slots - hSpatParamRendCom->slots_rendered ) * slot_size; + *nSamplesAvailable = ( hDirAC->num_slots - hDirAC->slots_rendered ) * slot_size; return; } @@ -442,13 +407,12 @@ void ivas_dirac_dec_binaural_render( #ifdef FIX_564 /*------------------------------------------------------------------------- - * ivas_dirac_dec_binaural_sba_gain() + * ivas_dirac_dec_binaural_gain() * * loudness correction for parametric binaural renderer *------------------------------------------------------------------------*/ -// Todo Tapani refactor: To be moved to lib_dec -void ivas_dirac_dec_binaural_sba_gain( +void ivas_dirac_dec_binaural_gain( float output[][L_FRAME48k], /* i/o: synthesized core-coder transport channels/DirAC output */ const int16_t nchan_remapped, /* i : num channels after remapping of TCs */ const int16_t output_frame /* i : output frame length */ @@ -482,7 +446,6 @@ void ivas_dirac_dec_binaural_sba_gain( * Parametric binaural renderer main function *------------------------------------------------------------------------*/ -// Todo Tapani refactor: To be moved to lib_dec void ivas_dirac_dec_binaural( Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, /* i : combined orientation handle */ @@ -491,13 +454,11 @@ void ivas_dirac_dec_binaural( ) { int16_t subframe; - SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom; float cng_td_buffer[L_FRAME16k]; float *p_output[MAX_OUTPUT_CHANNELS]; int16_t ch; int16_t slot_size; int16_t numInChannels; - hSpatParamRendCom = st_ivas->hSpatParamRendCom; slot_size = NS2SA( st_ivas->hDecoderConfig->output_Fs, CLDFB_SLOT_NS ); for ( ch = 0; ch < 2 * BINAURAL_CHANNELS; ch++ ) @@ -505,10 +466,22 @@ void ivas_dirac_dec_binaural( p_output[ch] = &output_f[ch][0]; } numInChannels = nchan_transport; +#ifdef MASA_AND_OBJECTS + if ( st_ivas->hOutSetup.separateChannelEnabled || ( st_ivas->ivas_format == MASA_ISM_FORMAT && ( st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) ) ) + { + numInChannels++; + } + else if ( st_ivas->ivas_format == MASA_ISM_FORMAT && st_ivas->ism_mode == ISM_MASA_MODE_DISC && ( st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) + { + numInChannels += (uint8_t) st_ivas->nchan_ism; + } +#else if ( st_ivas->hOutSetup.separateChannelEnabled ) { numInChannels++; } +#endif + for ( ch = 0; ch < numInChannels; ch++ ) { st_ivas->hTcBuffer->tc[ch] = &output_f[ch][0]; @@ -544,7 +517,7 @@ void ivas_dirac_dec_binaural( for ( subframe = 0; subframe < MAX_PARAM_SPATIAL_SUBFRAMES; subframe++ ) { - int16_t n_samples_sf = slot_size * hSpatParamRendCom->subframe_nbslots[subframe]; + int16_t n_samples_sf = slot_size * st_ivas->hDirAC->subframe_nbslots[subframe]; ivas_dirac_dec_binaural_internal( st_ivas, hCombinedOrientationData, p_output, nchan_transport, subframe ); @@ -552,7 +525,7 @@ void ivas_dirac_dec_binaural( { p_output[ch] += n_samples_sf; } - hSpatParamRendCom->dirac_read_idx = ( hSpatParamRendCom->dirac_read_idx + 1 ) % hSpatParamRendCom->dirac_md_buffer_length; + st_ivas->hDirAC->dirac_read_idx = ( st_ivas->hDirAC->dirac_read_idx + 1 ) % st_ivas->hDirAC->dirac_md_buffer_length; } for ( ch = 0; ch < 2 * BINAURAL_CHANNELS; ch++ ) @@ -568,7 +541,7 @@ void ivas_dirac_dec_binaural( * Local functions *------------------------------------------------------------------------*/ -// Todo refactor: To be moved to lib_dec + static void ivas_dirac_dec_binaural_internal( Decoder_Struct *st_ivas, COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, @@ -576,39 +549,42 @@ static void ivas_dirac_dec_binaural_internal( const int16_t nchan_transport, const int16_t subframe ) { - DIRAC_DEC_BIN_HANDLE hDiracDecBin; - SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom; - PARAMBIN_REND_CONFIG config_data; + DIRAC_DEC_HANDLE hDirAC; int16_t slot, ch, numInChannels; +#ifdef MASA_AND_OBJECTS + float Cldfb_RealBuffer_in[6][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + float Cldfb_ImagBuffer_in[6][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; +#else float Cldfb_RealBuffer_in[4][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; float Cldfb_ImagBuffer_in[4][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; +#endif float Rmat[3][3]; int16_t max_band_decorr; DIFFUSE_DISTRIBUTION_DATA diffuseDistData; int16_t nBins, offsetSamples; int16_t i, j; - hDiracDecBin = st_ivas->hDiracDecBin; - assert( hDiracDecBin ); - hSpatParamRendCom = st_ivas->hSpatParamRendCom; - nBins = hSpatParamRendCom->num_freq_bands; - offsetSamples = hSpatParamRendCom->slots_rendered * nBins; - - /* Setuo internal config */ - config_data.separateCenterChannelRendering = st_ivas->hOutSetup.separateChannelEnabled; - config_data.ivas_format = st_ivas->ivas_format; - config_data.mc_mode = st_ivas->mc_mode; - config_data.ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; - config_data.nchan_transport = st_ivas->nchan_transport; - config_data.qualityBasedSmFactor = st_ivas->hMasa != NULL ? st_ivas->hMasa->data.dir_decode_quality : 1.0f; - config_data.processReverb = st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ? 1 : 0; + hDirAC = st_ivas->hDirAC; + nBins = hDirAC->num_freq_bands; + offsetSamples = hDirAC->slots_rendered * nBins; /* The input channel number at this processing function (not nchan_transport) */ numInChannels = BINAURAL_CHANNELS; - if ( config_data.separateCenterChannelRendering ) +#ifdef MASA_AND_OBJECTS + if ( st_ivas->hOutSetup.separateChannelEnabled || ( st_ivas->ivas_format == MASA_ISM_FORMAT && ( st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) ) ) { numInChannels++; } + else if ( st_ivas->ivas_format == MASA_ISM_FORMAT && st_ivas->ism_mode == ISM_MASA_MODE_DISC && ( st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) + { + numInChannels += (uint8_t) st_ivas->nchan_ism; + } +#else + if ( st_ivas->hOutSetup.separateChannelEnabled ) + { + numInChannels++; + } +#endif Rmat[0][0] = 1.0f; Rmat[0][1] = 0.0f; @@ -623,7 +599,7 @@ static void ivas_dirac_dec_binaural_internal( Rmat[2][2] = 1.0f; /* CLDFB Analysis of input */ - for ( slot = 0; slot < hSpatParamRendCom->subframe_nbslots[subframe]; slot++ ) + for ( slot = 0; slot < hDirAC->subframe_nbslots[subframe]; slot++ ) { for ( ch = 0; ch < numInChannels; ch++ ) { @@ -635,7 +611,7 @@ static void ivas_dirac_dec_binaural_internal( Cldfb_ImagBuffer_in[ch][slot], nBins, st_ivas->cldfbAnaDec[ch] ); } - else if ( config_data.nchan_transport == 2 ) /* Stereo signal transmitted as mono with DFT stereo */ + else if ( st_ivas->nchan_transport == 2 ) /* Stereo signal transmitted as mono with DFT stereo */ { /* At mono input duplicate the channel to dual-mono */ mvr2r( Cldfb_RealBuffer_in[0][slot], Cldfb_RealBuffer_in[1][slot], nBins ); @@ -650,7 +626,7 @@ static void ivas_dirac_dec_binaural_internal( int16_t slotInFrame; numCoreBands = st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->numCoreBands; - slotInFrame = hSpatParamRendCom->slots_rendered + slot; + slotInFrame = hDirAC->slots_rendered + slot; generate_masking_noise_dirac( st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom, st_ivas->cldfbAnaDec[1], @@ -702,7 +678,7 @@ static void ivas_dirac_dec_binaural_internal( } } - if ( hDiracDecBin->useTdDecorr ) + if ( st_ivas->hDiracDecBin->useTdDecorr ) { for ( ch = BINAURAL_CHANNELS; ch < ( 2 * BINAURAL_CHANNELS ); ch++ ) { @@ -712,7 +688,7 @@ static void ivas_dirac_dec_binaural_internal( Cldfb_ImagBuffer_in[ch][slot], nBins, st_ivas->cldfbAnaDec[ch] ); - if ( config_data.nchan_transport == 1 && config_data.ivas_format == SBA_FORMAT ) + if ( st_ivas->nchan_transport == 1 && st_ivas->ivas_format == SBA_FORMAT ) { v_multc( Cldfb_RealBuffer_in[ch][slot], INV_SQRT_2, Cldfb_RealBuffer_in[ch][slot], nBins ); v_multc( Cldfb_ImagBuffer_in[ch][slot], INV_SQRT_2, Cldfb_ImagBuffer_in[ch][slot], nBins ); @@ -721,15 +697,22 @@ static void ivas_dirac_dec_binaural_internal( } } - if ( config_data.ivas_format == SBA_FORMAT ) + if ( st_ivas->ivas_format == SBA_FORMAT ) { - hDiracDecBin->hDiffuseDist = &diffuseDistData; + st_ivas->hDirAC->hDiffuseDist = &diffuseDistData; ivas_spar_param_to_masa_param_mapping( st_ivas, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, subframe ); ivas_sba_prototype_renderer( st_ivas, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, subframe ); } +#ifdef MASA_AND_OBJECTS + if ( st_ivas->ivas_format == MASA_ISM_FORMAT && nchan_transport == 2 && st_ivas->ism_mode != ISM_MASA_MODE_DISC && st_ivas->ism_mode != ISM_MASA_MODE_MASA_ONE_OBJ ) + { + preProcessStereoTransportsForMovedObjects( st_ivas, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, nBins, subframe ); + } +#endif + if ( hCombinedOrientationData ) { for ( i = 0; i < 3; i++ ) @@ -742,45 +725,44 @@ static void ivas_dirac_dec_binaural_internal( if ( nchan_transport == 2 ) { - adaptTransportSignalsHeadtracked( hCombinedOrientationData, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, nBins, hSpatParamRendCom->subframe_nbslots[subframe], Rmat ); + adaptTransportSignalsHeadtracked( hCombinedOrientationData, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, nBins, hDirAC->subframe_nbslots[subframe], Rmat ); - ivas_dirac_dec_binaural_check_and_switch_transports_headtracked( hCombinedOrientationData, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, nBins, hSpatParamRendCom->subframe_nbslots[subframe], Rmat ); + ivas_dirac_dec_binaural_check_and_switch_transports_headtracked( hCombinedOrientationData, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, nBins, hDirAC->subframe_nbslots[subframe], Rmat ); } } - ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, Rmat, subframe, + ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matrices( st_ivas, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, Rmat, subframe, hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[subframe] > 0 ); - if ( config_data.ivas_format == ISM_FORMAT ) + if ( st_ivas->ivas_format == ISM_FORMAT ) { max_band_decorr = 0; } - else if ( hDiracDecBin->useTdDecorr ) + else if ( st_ivas->hDiracDecBin->useTdDecorr ) { max_band_decorr = CLDFB_NO_CHANNELS_MAX; } else { - max_band_decorr = hDiracDecBin->h_freq_domain_decorr_ap_params->max_band_decorr; + max_band_decorr = st_ivas->hDirAC->h_freq_domain_decorr_ap_params->max_band_decorr; } - ivas_dirac_dec_binaural_determine_processing_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, max_band_decorr, Rmat, + ivas_dirac_dec_binaural_determine_processing_matrices( st_ivas, max_band_decorr, Rmat, hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[subframe] > 0 ); - ivas_dirac_dec_binaural_process_output( hDiracDecBin, hSpatParamRendCom, st_ivas->cldfbSynDec, output_f, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, max_band_decorr, numInChannels, config_data.processReverb, subframe ); + ivas_dirac_dec_binaural_process_output( st_ivas, output_f, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, max_band_decorr, numInChannels, subframe ); - hDiracDecBin->hDiffuseDist = NULL; + st_ivas->hDirAC->hDiffuseDist = NULL; - - hSpatParamRendCom->slots_rendered += hSpatParamRendCom->subframe_nbslots[subframe]; - hSpatParamRendCom->subframes_rendered++; + // Todo OMASA JBM: This change could have some side effects + hDirAC->slots_rendered += hDirAC->subframe_nbslots[subframe]; + hDirAC->subframes_rendered++; return; } static void ivas_dirac_dec_decorrelate_slot( - DIRAC_DEC_BIN_HANDLE hDiracDecBin, - const int16_t num_freq_bands, + DIRAC_DEC_HANDLE hDirAC, const int16_t slot, float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], @@ -790,39 +772,37 @@ static void ivas_dirac_dec_decorrelate_slot( int16_t offset, ch, bin; float onset_filter[BINAURAL_CHANNELS * CLDFB_NO_CHANNELS_MAX]; /* 2 ch, 60 bins */ float decorrelatedFrameInterleaved[2 * BINAURAL_CHANNELS * CLDFB_NO_CHANNELS_MAX]; /* 2 ch, real + imag, 60 bins */ - float protoFrameF[2 * BINAURAL_CHANNELS * CLDFB_NO_CHANNELS_MAX]; /* 2 ch, real + imag, 60 bins */ - const int16_t protoIndexDir[BINAURAL_CHANNELS] = { 0, 1 }; /* Decorrelation needs interleaved data. Copy left and right signals to proto_frame_f */ for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) { - offset = num_freq_bands * BINAURAL_CHANNELS * ch; - for ( bin = 0; bin < num_freq_bands; bin++ ) + offset = hDirAC->num_freq_bands * BINAURAL_CHANNELS * ch; + for ( bin = 0; bin < hDirAC->num_freq_bands; bin++ ) { - protoFrameF[( bin * BINAURAL_CHANNELS ) + offset] = inRe[ch][slot][bin]; - protoFrameF[( bin * BINAURAL_CHANNELS ) + offset + 1] = inIm[ch][slot][bin]; + hDirAC->proto_frame_f[( bin * BINAURAL_CHANNELS ) + offset] = inRe[ch][slot][bin]; + hDirAC->proto_frame_f[( bin * BINAURAL_CHANNELS ) + offset + 1] = inIm[ch][slot][bin]; } } /* Decorrelate proto signal to decorrelatedFrameInterleaved */ - ivas_dirac_dec_decorr_process( num_freq_bands, - BINAURAL_CHANNELS, - BINAURAL_CHANNELS, - DIRAC_SYNTHESIS_PSD_LS, + ivas_dirac_dec_decorr_process( hDirAC->num_freq_bands, + hDirAC->num_outputs_diff, + hDirAC->num_protos_diff, + hDirAC->synthesisConf, BINAURAL_CHANNELS, - protoFrameF, - BINAURAL_CHANNELS, - protoIndexDir, + hDirAC->proto_frame_f, + hDirAC->num_protos_diff, + hDirAC->proto_index_diff, decorrelatedFrameInterleaved, onset_filter, - hDiracDecBin->h_freq_domain_decorr_ap_params, - hDiracDecBin->h_freq_domain_decorr_ap_state ); + hDirAC->h_freq_domain_decorr_ap_params, + hDirAC->h_freq_domain_decorr_ap_state ); /* De-interleave decorrelated signals*/ for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) { - offset = num_freq_bands * BINAURAL_CHANNELS * ch; - for ( bin = 0; bin < num_freq_bands; bin++ ) + offset = hDirAC->num_freq_bands * BINAURAL_CHANNELS * ch; + for ( bin = 0; bin < hDirAC->num_freq_bands; bin++ ) { decRe[ch][bin] = decorrelatedFrameInterleaved[( bin * BINAURAL_CHANNELS ) + offset]; decIm[ch][bin] = decorrelatedFrameInterleaved[( bin * BINAURAL_CHANNELS ) + offset + 1]; @@ -834,9 +814,7 @@ static void ivas_dirac_dec_decorrelate_slot( static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matrices( - DIRAC_DEC_BIN_HANDLE hDiracDecBin, - SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, - PARAMBIN_REND_CONFIG_HANDLE hConfig, + Decoder_Struct *st_ivas, float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float Rmat[3][3], @@ -844,9 +822,11 @@ static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matric const int16_t isHeadtracked ) { int16_t ch, slot, bin; - int16_t separateCenterChannelRendering; + uint8_t separateCenterChannelRendering; int16_t nBins, idx; float frameMeanDiffusenessEneWeight[CLDFB_NO_CHANNELS_MAX]; + DIRAC_DEC_HANDLE hDirAC; + DIRAC_DEC_BIN_HANDLE h; float IIReneLimiterFactor; float qualityBasedSmFactor; float lowBitRateEQ[CLDFB_NO_CHANNELS_MAX]; @@ -854,30 +834,25 @@ static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matric int16_t dirac_read_idx; float subFrameTotalEne[CLDFB_NO_CHANNELS_MAX]; PARAMBIN_HRTF_GAIN_CACHE gainCache[MAX_GAIN_CACHE_SIZE]; - IVAS_FORMAT ivas_format; - MC_MODE mc_mode; - int32_t ivas_total_brate; - int16_t nchan_transport; - - separateCenterChannelRendering = hConfig->separateCenterChannelRendering; - ivas_format = hConfig->ivas_format; - mc_mode = hConfig->mc_mode; - ivas_total_brate = hConfig->ivas_total_brate; - nchan_transport = hConfig->nchan_transport; - qualityBasedSmFactor = hConfig->qualityBasedSmFactor; - qualityBasedSmFactor *= qualityBasedSmFactor; - nBins = hSpatParamRendCom->num_freq_bands; /* Actually bins */ - - set_zero( hDiracDecBin->ChCrossRe, nBins ); - set_zero( hDiracDecBin->ChCrossIm, nBins ); - set_zero( hDiracDecBin->ChCrossReOut, nBins ); - set_zero( hDiracDecBin->ChCrossImOut, nBins ); +#ifdef MASA_AND_OBJECTS + int16_t gainCacheBaseIndex; +#endif + + hDirAC = st_ivas->hDirAC; + h = st_ivas->hDiracDecBin; + separateCenterChannelRendering = st_ivas->hOutSetup.separateChannelEnabled; + nBins = hDirAC->num_freq_bands; /* Actually bins */ + + set_zero( h->ChCrossRe, nBins ); + set_zero( h->ChCrossIm, nBins ); + set_zero( h->ChCrossReOut, nBins ); + set_zero( h->ChCrossImOut, nBins ); for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) { - set_zero( hDiracDecBin->ChEne[ch], nBins ); - set_zero( hDiracDecBin->ChEneOut[ch], nBins ); + set_zero( h->ChEne[ch], nBins ); + set_zero( h->ChEneOut[ch], nBins ); } - set_zero( hDiracDecBin->frameMeanDiffuseness, nBins ); + set_zero( h->frameMeanDiffuseness, nBins ); set_zero( frameMeanDiffusenessEneWeight, CLDFB_NO_CHANNELS_MAX ); @@ -888,10 +863,10 @@ static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matric /* Determine EQ for low bit rates (13.2 and 16.4 kbps) */ applyLowBitRateEQ = 0; - if ( ( ivas_format == MASA_FORMAT || ivas_format == MC_FORMAT ) && ivas_total_brate < MASA_STEREO_MIN_BITRATE ) + if ( ( st_ivas->ivas_format == MASA_FORMAT || st_ivas->ivas_format == MC_FORMAT ) && st_ivas->hDecoderConfig->ivas_total_brate < MASA_STEREO_MIN_BITRATE ) { applyLowBitRateEQ = 1; - if ( ivas_total_brate == IVAS_16k4 ) + if ( st_ivas->hDecoderConfig->ivas_total_brate == IVAS_16k4 ) { for ( bin = 0; bin < LOW_BIT_RATE_BINAURAL_EQ_BINS; bin++ ) { @@ -909,10 +884,10 @@ static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matric /* Formulate input and target covariance matrices for this subframe */ set_zero( subFrameTotalEne, CLDFB_NO_CHANNELS_MAX ); - dirac_read_idx = hSpatParamRendCom->render_to_md_map[subframe]; + dirac_read_idx = hDirAC->render_to_md_map[subframe]; /* Calculate input covariance matrix */ - for ( slot = 0; slot < hSpatParamRendCom->subframe_nbslots[subframe]; slot++ ) + for ( slot = 0; slot < hDirAC->subframe_nbslots[subframe]; slot++ ) { for ( bin = 0; bin < nBins; bin++ ) { @@ -922,13 +897,13 @@ static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matric instEne = ( inRe[ch][slot][bin] * inRe[ch][slot][bin] ); instEne += ( inIm[ch][slot][bin] * inIm[ch][slot][bin] ); - hDiracDecBin->ChEne[ch][bin] += instEne; + h->ChEne[ch][bin] += instEne; subFrameTotalEne[bin] += instEne; } - hDiracDecBin->ChCrossRe[bin] += inRe[0][slot][bin] * inRe[1][slot][bin]; - hDiracDecBin->ChCrossRe[bin] += inIm[0][slot][bin] * inIm[1][slot][bin]; - hDiracDecBin->ChCrossIm[bin] += inRe[0][slot][bin] * inIm[1][slot][bin]; - hDiracDecBin->ChCrossIm[bin] -= inIm[0][slot][bin] * inRe[1][slot][bin]; + h->ChCrossRe[bin] += inRe[0][slot][bin] * inRe[1][slot][bin]; + h->ChCrossRe[bin] += inIm[0][slot][bin] * inIm[1][slot][bin]; + h->ChCrossIm[bin] += inRe[0][slot][bin] * inIm[1][slot][bin]; + h->ChCrossIm[bin] -= inIm[0][slot][bin] * inRe[1][slot][bin]; } } @@ -947,13 +922,13 @@ static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matric } } - if ( ivas_format == SBA_FORMAT && nchan_transport == 2 ) + if ( st_ivas->ivas_format == SBA_FORMAT && st_ivas->nchan_transport == 2 ) { float tempRe, tempIm; set_zero( subFrameTotalEne, CLDFB_NO_CHANNELS_MAX ); - for ( slot = 0; slot < hSpatParamRendCom->subframe_nbslots[subframe]; slot++ ) + for ( slot = 0; slot < hDirAC->subframe_nbslots[subframe]; slot++ ) { for ( bin = 0; bin < nBins; bin++ ) { @@ -967,7 +942,11 @@ static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matric /* Determine target covariance matrix containing target binaural properties */ for ( bin = 0; bin < nBins; bin++ ) { - float diffuseness = 1.0f; /* ratio1 and ratio2 are subtracted from diffuseness further below */ + float diffuseness = 1.0f; /* ratio1 and ratio2 are subtracted from diffuseness further below */ +#ifdef MASA_AND_OBJECTS + float diffusenessValForDecorrelationReduction = 1.0f; + float diffEneValForDecorrelationReduction; +#endif float surCoh = 0.0f, spreadCoh = 0.0f; /* Default values if spreadSurroundCoherenceApplied == false */ float diffEne, dirEne, meanEnePerCh; int16_t dirIndex; @@ -977,26 +956,36 @@ static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matric * HRTF data set and a BRIR-based data set. The HRTF data set is spectrally corrected to match * the early spectrum of the BRIR data, using the spectral correction data in * hBinaural->earlyPartEneCorrection[bin], based on the BRIR set. */ - meanEnePerCh = hDiracDecBin->earlyPartEneCorrection[bin] * subFrameTotalEne[bin] / 2.0f; + meanEnePerCh = h->earlyPartEneCorrection[bin] * subFrameTotalEne[bin] / 2.0f; /* Determine direct part target covariance matrix (for 1 or 2 directions) */ - for ( dirIndex = 0; dirIndex < hSpatParamRendCom->numSimultaneousDirections; dirIndex++ ) + for ( dirIndex = 0; dirIndex < hDirAC->numSimultaneousDirections; dirIndex++ ) { int16_t aziDeg, eleDeg; float lRealp, lImagp, rRealp, rImagp; float lRealpTmp, lImagpTmp, rRealpTmp, rImagpTmp; float hrtfEne[BINAURAL_CHANNELS], hrtfCrossRe, hrtfCrossIm, ratio; +#ifdef MASA_AND_OBJECTS + uint8_t isIsmDirection = 0; +#endif if ( dirIndex == 0 ) /* For first of the two simultaneous directions */ { - aziDeg = hSpatParamRendCom->azimuth[dirac_read_idx][bin]; - eleDeg = hSpatParamRendCom->elevation[dirac_read_idx][bin]; - ratio = hSpatParamRendCom->energy_ratio1[dirac_read_idx][bin]; - spreadCoh = hSpatParamRendCom->spreadCoherence[dirac_read_idx][bin]; + aziDeg = hDirAC->azimuth[dirac_read_idx][bin]; + eleDeg = hDirAC->elevation[dirac_read_idx][bin]; + ratio = hDirAC->energy_ratio1[dirac_read_idx][bin]; + spreadCoh = hDirAC->spreadCoherence[dirac_read_idx][bin]; +#ifdef MASA_AND_OBJECTS + gainCacheBaseIndex = 0; +#endif } +#ifdef MASA_AND_OBJECTS + else if ( st_ivas->ivas_format != MASA_ISM_FORMAT || ( st_ivas->ivas_format == MASA_ISM_FORMAT && dirIndex < hDirAC->numParametricDirections ) ) /* For second of the two simultaneous directions */ +#else else /* For second of the two simultaneous directions */ +#endif { - if ( ( ratio = hSpatParamRendCom->energy_ratio2[dirac_read_idx][bin] ) < 0.001 ) + if ( ( ratio = hDirAC->energy_ratio2[dirac_read_idx][bin] ) < 0.001 ) { /* This touches only MASA path where second direction always has smaller ratio and * for non-2dir it is zero. As the whole direction contribution is multiplied with @@ -1004,12 +993,53 @@ static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matric * it is better to save complexity. */ continue; } - aziDeg = hSpatParamRendCom->azimuth2[dirac_read_idx][bin]; - eleDeg = hSpatParamRendCom->elevation2[dirac_read_idx][bin]; - spreadCoh = hSpatParamRendCom->spreadCoherence2[dirac_read_idx][bin]; + aziDeg = hDirAC->azimuth2[dirac_read_idx][bin]; + eleDeg = hDirAC->elevation2[dirac_read_idx][bin]; + spreadCoh = hDirAC->spreadCoherence2[dirac_read_idx][bin]; +#ifdef MASA_AND_OBJECTS + gainCacheBaseIndex = 3; +#endif } +#ifdef MASA_AND_OBJECTS + else /* For object directions of MASA_ISM_FORMAT */ + { + isIsmDirection = 1; + uint16_t ismDirIndex; + ismDirIndex = dirIndex - hDirAC->numParametricDirections; + if ( st_ivas->hMasaIsmData->ism_is_edited[ismDirIndex] ) + { + aziDeg = st_ivas->hMasaIsmData->azimuth_ism_edited[ismDirIndex]; + eleDeg = st_ivas->hMasaIsmData->elevation_ism_edited[ismDirIndex]; + } + else + { + aziDeg = st_ivas->hMasaIsmData->azimuth_ism[ismDirIndex][dirac_read_idx]; + eleDeg = st_ivas->hMasaIsmData->elevation_ism[ismDirIndex][dirac_read_idx]; + } + ratio = st_ivas->hMasaIsmData->energy_ratio_ism[ismDirIndex][dirac_read_idx][bin]; + spreadCoh = 0.0f; + gainCacheBaseIndex = 6 + ismDirIndex; + } +#endif + diffuseness -= ratio; /* diffuseness = 1 - ratio1 - ratio2 */ +#ifdef MASA_AND_OBJECTS + if ( diffuseness < 0.0f ) + { + diffuseness = 0.0f; + } + if ( isIsmDirection ) + { + /* Objects cause lesser decorrelation reduction, to avoid removing all decorrelation when only objects are present */ + diffusenessValForDecorrelationReduction -= ratio * 0.5f; + } + else + { + diffusenessValForDecorrelationReduction -= ratio; + } +#endif + if ( separateCenterChannelRendering ) { /* In masa + mono rendering mode, the center directions originate from phantom sources, so the @@ -1024,9 +1054,13 @@ static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matric spreadCoh = max( spreadCoh, altSpreadCoh ); } - getDirectPartGains( bin, aziDeg, eleDeg, &lRealp, &lImagp, &rRealp, &rImagp, hDiracDecBin->renderStereoOutputInsteadOfBinaural, Rmat, &gainCache[( dirIndex * 3 )], isHeadtracked ); +#ifdef MASA_AND_OBJECTS + getDirectPartGains( bin, aziDeg, eleDeg, &lRealp, &lImagp, &rRealp, &rImagp, h->renderStereoOutputInsteadOfBinaural, Rmat, &gainCache[gainCacheBaseIndex], isHeadtracked ); +#else + getDirectPartGains( bin, aziDeg, eleDeg, &lRealp, &lImagp, &rRealp, &rImagp, h->renderStereoOutputInsteadOfBinaural, Rmat, &gainCache[( dirIndex * 3 )], isHeadtracked ); +#endif - if ( hDiracDecBin->renderStereoOutputInsteadOfBinaural ) + if ( h->renderStereoOutputInsteadOfBinaural ) { /* Synthesizing spread coherence is not needed for stereo loudspeaker output, * as directional sound is reproduced with two loudspeakers in any case */ @@ -1067,7 +1101,11 @@ static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matric rImagp *= centerMul; /* Apply the gain for the left source of the three coherent sources */ - getDirectPartGains( bin, aziDeg + 30, eleDeg, &lRealpTmp, &lImagpTmp, &rRealpTmp, &rImagpTmp, hDiracDecBin->renderStereoOutputInsteadOfBinaural, Rmat, &gainCache[( dirIndex * 3 + 1 )], isHeadtracked ); +#ifdef MASA_AND_OBJECTS + getDirectPartGains( bin, aziDeg + 30, eleDeg, &lRealpTmp, &lImagpTmp, &rRealpTmp, &rImagpTmp, h->renderStereoOutputInsteadOfBinaural, Rmat, &gainCache[gainCacheBaseIndex + 1], isHeadtracked ); +#else + getDirectPartGains( bin, aziDeg + 30, eleDeg, &lRealpTmp, &lImagpTmp, &rRealpTmp, &rImagpTmp, h->renderStereoOutputInsteadOfBinaural, Rmat, &gainCache[( dirIndex * 3 + 1 )], isHeadtracked ); +#endif hrtfEneSides = ( lRealpTmp * lRealpTmp ) + ( lImagpTmp * lImagpTmp ) + ( rRealpTmp * rRealpTmp ) + ( rImagpTmp * rImagpTmp ); lRealp += sidesMul * lRealpTmp; @@ -1077,7 +1115,11 @@ static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matric /* Apply the gain for the right source of the three coherent sources. * -30 degrees to 330 wrapping due to internal functions. */ - getDirectPartGains( bin, aziDeg + 330, eleDeg, &lRealpTmp, &lImagpTmp, &rRealpTmp, &rImagpTmp, hDiracDecBin->renderStereoOutputInsteadOfBinaural, Rmat, &gainCache[( dirIndex * 3 + 2 )], isHeadtracked ); +#ifdef MASA_AND_OBJECTS + getDirectPartGains( bin, aziDeg + 330, eleDeg, &lRealpTmp, &lImagpTmp, &rRealpTmp, &rImagpTmp, h->renderStereoOutputInsteadOfBinaural, Rmat, &gainCache[gainCacheBaseIndex + 2], isHeadtracked ); +#else + getDirectPartGains( bin, aziDeg + 330, eleDeg, &lRealpTmp, &lImagpTmp, &rRealpTmp, &rImagpTmp, h->renderStereoOutputInsteadOfBinaural, Rmat, &gainCache[( dirIndex * 3 + 2 )], isHeadtracked ); +#endif hrtfEneSides += ( lRealpTmp * lRealpTmp ) + ( lImagpTmp * lImagpTmp ) + ( rRealpTmp * rRealpTmp ) + ( rImagpTmp * rImagpTmp ); lRealp += sidesMul * lRealpTmp; @@ -1105,7 +1147,7 @@ static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matric w3 = 2.0f * spreadCoh - 1.0f; } - if ( ( ivas_format == MC_FORMAT && mc_mode == MC_MODE_MCMASA ) ) + if ( ( st_ivas->ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCMASA ) ) { idx = min( bin, MASA_NUM_DEFINED_SUR_SPR_COH_ENE_BINS - 1 ); @@ -1135,60 +1177,92 @@ static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matric /* Add direct part (1 or 2) covariance matrix */ dirEne = ratio * meanEnePerCh; - hDiracDecBin->ChEneOut[0][bin] += dirEne * hrtfEne[0]; /* Dir ene part*/ - hDiracDecBin->ChEneOut[1][bin] += dirEne * hrtfEne[1]; - hDiracDecBin->ChCrossReOut[bin] += dirEne * hrtfCrossRe; /* Dir cross re */ - hDiracDecBin->ChCrossImOut[bin] += dirEne * hrtfCrossIm; /* Dir cross im */ + h->ChEneOut[0][bin] += dirEne * hrtfEne[0]; /* Dir ene part*/ + h->ChEneOut[1][bin] += dirEne * hrtfEne[1]; + h->ChCrossReOut[bin] += dirEne * hrtfCrossRe; /* Dir cross re */ + h->ChCrossImOut[bin] += dirEne * hrtfCrossIm; /* Dir cross im */ } /* Add diffuse / ambient part covariance matrix */ diffuseness = max( 0.0f, diffuseness ); diffEne = diffuseness * meanEnePerCh; - surCoh = hSpatParamRendCom->surroundingCoherence[dirac_read_idx][bin]; - if ( ( ivas_format == MC_FORMAT && mc_mode == MC_MODE_MCMASA ) ) + surCoh = hDirAC->surroundingCoherence[dirac_read_idx][bin]; + +#ifdef MASA_AND_OBJECTS + diffusenessValForDecorrelationReduction = max( 0.0f, diffusenessValForDecorrelationReduction ); + diffEneValForDecorrelationReduction = diffusenessValForDecorrelationReduction * meanEnePerCh; +#endif + + if ( ( st_ivas->ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCMASA ) ) { - if ( !hDiracDecBin->renderStereoOutputInsteadOfBinaural ) + if ( !h->renderStereoOutputInsteadOfBinaural ) { +#ifdef MASA_AND_OBJECTS + float spectrumModVal; + + idx = min( bin, MASA_NUM_DEFINED_SUR_SPR_COH_ENE_BINS - 1 ); + /* Apply target spectrum that emphasizes low frequencies when the sound is surround coherent */ + spectrumModVal = ( 1.0f - surCoh ) + surCoh * surCohEne[idx]; + diffEne *= spectrumModVal; +#else idx = min( bin, MASA_NUM_DEFINED_SUR_SPR_COH_ENE_BINS - 1 ); /* Apply target spectrum that emphasizes low frequencies when the sound is surround coherent */ diffEne *= ( 1.0f - surCoh ) + surCoh * surCohEne[idx]; +#endif + +#ifdef MASA_AND_OBJECTS + /* Modify also the value for decorrelation reduction */ + diffEneValForDecorrelationReduction *= spectrumModVal; +#endif } } - hDiracDecBin->ChEneOut[0][bin] += diffEne; /* Diff ene part*/ - hDiracDecBin->ChEneOut[1][bin] += diffEne; + h->ChEneOut[0][bin] += diffEne; /* Diff ene part*/ + h->ChEneOut[1][bin] += diffEne; - if ( hDiracDecBin->renderStereoOutputInsteadOfBinaural ) + if ( h->renderStereoOutputInsteadOfBinaural ) { /* When rendering stereo, ambience (except for surround coherent sound) has zero ICC. */ - hDiracDecBin->ChCrossReOut[bin] += surCoh * diffEne; + h->ChCrossReOut[bin] += surCoh * diffEne; } else /* When rendering binaural, ambience has frequency dependent ICC. */ { - if ( ivas_format == SBA_FORMAT && bin < BINAURAL_COHERENCE_DIFFERENCE_BINS ) + if ( st_ivas->ivas_format == SBA_FORMAT && bin < BINAURAL_COHERENCE_DIFFERENCE_BINS ) { float diffuseFieldCoherence; - diffuseFieldCoherence = hDiracDecBin->hDiffuseDist->diffuseRatioX[bin] * hDiracDecBin->diffuseFieldCoherenceX[bin] + hDiracDecBin->hDiffuseDist->diffuseRatioY[bin] * hDiracDecBin->diffuseFieldCoherenceY[bin] + hDiracDecBin->hDiffuseDist->diffuseRatioZ[bin] * hDiracDecBin->diffuseFieldCoherenceZ[bin]; - hDiracDecBin->ChCrossReOut[bin] += ( ( 1.0f - surCoh ) * diffuseFieldCoherence + surCoh ) * diffEne; + diffuseFieldCoherence = hDirAC->hDiffuseDist->diffuseRatioX[bin] * h->diffuseFieldCoherenceX[bin] + hDirAC->hDiffuseDist->diffuseRatioY[bin] * h->diffuseFieldCoherenceY[bin] + hDirAC->hDiffuseDist->diffuseRatioZ[bin] * h->diffuseFieldCoherenceZ[bin]; + h->ChCrossReOut[bin] += ( ( 1.0f - surCoh ) * diffuseFieldCoherence + surCoh ) * diffEne; } else { - hDiracDecBin->ChCrossReOut[bin] += ( ( 1.0f - surCoh ) * hDiracDecBin->diffuseFieldCoherence[bin] + surCoh ) * diffEne; + h->ChCrossReOut[bin] += ( ( 1.0f - surCoh ) * h->diffuseFieldCoherence[bin] + surCoh ) * diffEne; } } /* Store parameters for formulating average diffuseness over frame */ - hDiracDecBin->frameMeanDiffuseness[bin] += diffEne; +#ifdef MASA_AND_OBJECTS + h->frameMeanDiffuseness[bin] += diffEneValForDecorrelationReduction; +#else + h->frameMeanDiffuseness[bin] += diffEne; +#endif frameMeanDiffusenessEneWeight[bin] += meanEnePerCh; } /* Formulate average diffuseness over frame */ for ( bin = 0; bin < nBins; bin++ ) { - hDiracDecBin->frameMeanDiffuseness[bin] /= fmaxf( 1e-12f, frameMeanDiffusenessEneWeight[bin] ); + h->frameMeanDiffuseness[bin] /= fmaxf( 1e-12f, frameMeanDiffusenessEneWeight[bin] ); + } + + /* Determine encoding quality based additional smoothing factor */ + qualityBasedSmFactor = 1.0f; + if ( st_ivas->hMasa != NULL ) + { + qualityBasedSmFactor = st_ivas->hMasa->data.dir_decode_quality; + qualityBasedSmFactor *= qualityBasedSmFactor; } - /* Temporal IIR-type smoothing of covariance matrices. Also apply encoding quality based smoothing factor. */ - if ( ivas_format == MASA_FORMAT && ivas_total_brate < MASA_STEREO_MIN_BITRATE ) + /* Temporal IIR-type smoothing of covariance matrices */ + if ( st_ivas->ivas_format == MASA_FORMAT && st_ivas->hDecoderConfig->ivas_total_brate < MASA_STEREO_MIN_BITRATE ) { IIReneLimiterFactor = 16.0f + ( 1.0f - qualityBasedSmFactor ); } @@ -1203,41 +1277,41 @@ static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matric /* Temporally smooth cov mtx estimates for resulting mixing matrix stability. The design principle is that * the energy history (IIR) must not be more than double of the current frame energy. This provides more * robust performance at energy offsets when compared to typical IIR averaging. */ - eneRatio = ( hDiracDecBin->ChEne[0][bin] + hDiracDecBin->ChEne[1][bin] ) / fmaxf( 1e-12f, ( hDiracDecBin->ChEnePrev[0][bin] + hDiracDecBin->ChEnePrev[1][bin] ) ); + eneRatio = ( h->ChEne[0][bin] + h->ChEne[1][bin] ) / fmaxf( 1e-12f, ( h->ChEnePrev[0][bin] + h->ChEnePrev[1][bin] ) ); IIReneLimiter = fminf( 1.0f, eneRatio * IIReneLimiterFactor ); - hDiracDecBin->ChCrossRe[bin] *= qualityBasedSmFactor; - hDiracDecBin->ChCrossIm[bin] *= qualityBasedSmFactor; - hDiracDecBin->ChCrossReOut[bin] *= qualityBasedSmFactor; - hDiracDecBin->ChCrossImOut[bin] *= qualityBasedSmFactor; + h->ChCrossRe[bin] *= qualityBasedSmFactor; + h->ChCrossIm[bin] *= qualityBasedSmFactor; + h->ChCrossReOut[bin] *= qualityBasedSmFactor; + h->ChCrossImOut[bin] *= qualityBasedSmFactor; for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) { - hDiracDecBin->ChEne[ch][bin] *= qualityBasedSmFactor; - hDiracDecBin->ChEneOut[ch][bin] *= qualityBasedSmFactor; + h->ChEne[ch][bin] *= qualityBasedSmFactor; + h->ChEneOut[ch][bin] *= qualityBasedSmFactor; } - hDiracDecBin->ChCrossRe[bin] += IIReneLimiter * hDiracDecBin->ChCrossRePrev[bin]; - hDiracDecBin->ChCrossIm[bin] += IIReneLimiter * hDiracDecBin->ChCrossImPrev[bin]; - hDiracDecBin->ChCrossReOut[bin] += IIReneLimiter * hDiracDecBin->ChCrossReOutPrev[bin]; - hDiracDecBin->ChCrossImOut[bin] += IIReneLimiter * hDiracDecBin->ChCrossImOutPrev[bin]; + h->ChCrossRe[bin] += IIReneLimiter * h->ChCrossRePrev[bin]; + h->ChCrossIm[bin] += IIReneLimiter * h->ChCrossImPrev[bin]; + h->ChCrossReOut[bin] += IIReneLimiter * h->ChCrossReOutPrev[bin]; + h->ChCrossImOut[bin] += IIReneLimiter * h->ChCrossImOutPrev[bin]; for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) { - hDiracDecBin->ChEne[ch][bin] += IIReneLimiter * hDiracDecBin->ChEnePrev[ch][bin]; - hDiracDecBin->ChEneOut[ch][bin] += IIReneLimiter * hDiracDecBin->ChEneOutPrev[ch][bin]; + h->ChEne[ch][bin] += IIReneLimiter * h->ChEnePrev[ch][bin]; + h->ChEneOut[ch][bin] += IIReneLimiter * h->ChEneOutPrev[ch][bin]; } /* Store energy values and coefficients for next round */ - hDiracDecBin->ChCrossRePrev[bin] = hDiracDecBin->ChCrossRe[bin]; - hDiracDecBin->ChCrossImPrev[bin] = hDiracDecBin->ChCrossIm[bin]; - hDiracDecBin->ChCrossReOutPrev[bin] = hDiracDecBin->ChCrossReOut[bin]; - hDiracDecBin->ChCrossImOutPrev[bin] = hDiracDecBin->ChCrossImOut[bin]; + h->ChCrossRePrev[bin] = h->ChCrossRe[bin]; + h->ChCrossImPrev[bin] = h->ChCrossIm[bin]; + h->ChCrossReOutPrev[bin] = h->ChCrossReOut[bin]; + h->ChCrossImOutPrev[bin] = h->ChCrossImOut[bin]; for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) { - hDiracDecBin->ChEnePrev[ch][bin] = hDiracDecBin->ChEne[ch][bin]; - hDiracDecBin->ChEneOutPrev[ch][bin] = hDiracDecBin->ChEneOut[ch][bin]; + h->ChEnePrev[ch][bin] = h->ChEne[ch][bin]; + h->ChEneOutPrev[ch][bin] = h->ChEneOut[ch][bin]; } } @@ -1246,30 +1320,61 @@ static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matric static void ivas_dirac_dec_binaural_determine_processing_matrices( - DIRAC_DEC_BIN_HANDLE hDiracDecBin, - SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, - PARAMBIN_REND_CONFIG_HANDLE hConfig, + Decoder_Struct *st_ivas, const int16_t max_band_decorr, float Rmat[3][3], const int16_t isHeadtracked ) { int16_t chA, chB, bin; - int16_t separateCenterChannelRendering; + uint8_t separateCenterChannelRendering; +#ifdef MASA_AND_OBJECTS + uint8_t nchanSeparateChannels; +#endif int16_t nBins; +#ifdef MASA_AND_OBJECTS + int16_t dirac_read_idx; +#endif + DIRAC_DEC_BIN_HANDLE h; +#ifdef MASA_AND_OBJECTS + PARAMBIN_HRTF_GAIN_CACHE gainCache[MAX_NUM_OBJECTS]; + int16_t idx; +#else PARAMBIN_HRTF_GAIN_CACHE gainCache; - IVAS_FORMAT ivas_format; - MC_MODE mc_mode; - int32_t ivas_total_brate; - int16_t nchan_transport; - - separateCenterChannelRendering = hConfig->separateCenterChannelRendering; - ivas_format = hConfig->ivas_format; - mc_mode = hConfig->mc_mode; - ivas_total_brate = hConfig->ivas_total_brate; - nchan_transport = hConfig->nchan_transport; - nBins = hSpatParamRendCom->num_freq_bands; /* Actually bins */ +#endif + + h = st_ivas->hDiracDecBin; +#ifdef MASA_AND_OBJECTS + separateCenterChannelRendering = 0; + nchanSeparateChannels = 0; + if ( st_ivas->hOutSetup.separateChannelEnabled || ( st_ivas->ivas_format == MASA_ISM_FORMAT && ( st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) ) ) + { + separateCenterChannelRendering = 1; + nchanSeparateChannels = 1; + } + else if ( st_ivas->ivas_format == MASA_ISM_FORMAT && st_ivas->ism_mode == ISM_MASA_MODE_DISC && ( st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) + { + separateCenterChannelRendering = 1; + nchanSeparateChannels = (uint8_t) st_ivas->nchan_ism; + } +#else + separateCenterChannelRendering = st_ivas->hOutSetup.separateChannelEnabled; +#endif + + nBins = st_ivas->hDirAC->num_freq_bands; /* Actually bins */ +#ifdef MASA_AND_OBJECTS + // Todo OMASA JBM: This is probably not correct now. We should get the index from JBM + dirac_read_idx = st_ivas->hDirAC->dirac_read_idx; +#endif + +#ifdef MASA_AND_OBJECTS + for ( idx = 0; idx < MAX_NUM_OBJECTS; idx++ ) + { + gainCache[idx].azi = -1000; /* Use -1000 as value for uninitialized cache. */ + } +#else gainCache.azi = -1000; /* Use -1000 as value for uninitialized cache. */ +#endif for ( bin = 0; bin < nBins; bin++ ) { @@ -1285,21 +1390,21 @@ static void ivas_dirac_dec_binaural_determine_processing_matrices( CrEneR = 0.0f; /* Formulate main processing matrix M */ - formulate2x2MixingMatrix( hDiracDecBin->ChEne[0][bin], hDiracDecBin->ChEne[1][bin], - hDiracDecBin->ChCrossRe[bin], hDiracDecBin->ChCrossIm[bin], - hDiracDecBin->ChEneOut[0][bin], hDiracDecBin->ChEneOut[1][bin], - hDiracDecBin->ChCrossReOut[bin], hDiracDecBin->ChCrossImOut[bin], - prototypeMtx, Mre, Mim, hDiracDecBin->reqularizationFactor ); + formulate2x2MixingMatrix( h->ChEne[0][bin], h->ChEne[1][bin], + h->ChCrossRe[bin], h->ChCrossIm[bin], + h->ChEneOut[0][bin], h->ChEneOut[1][bin], + h->ChCrossReOut[bin], h->ChCrossImOut[bin], + prototypeMtx, Mre, Mim, h->reqularizationFactor ); /* Load estimated covariance matrix to the [2][2] matrix form */ - CxRe[0][0] = hDiracDecBin->ChEne[0][bin]; - CxRe[1][1] = hDiracDecBin->ChEne[1][bin]; - CxRe[1][0] = hDiracDecBin->ChCrossRe[bin]; - CxRe[0][1] = hDiracDecBin->ChCrossRe[bin]; + CxRe[0][0] = h->ChEne[0][bin]; + CxRe[1][1] = h->ChEne[1][bin]; + CxRe[1][0] = h->ChCrossRe[bin]; + CxRe[0][1] = h->ChCrossRe[bin]; CxIm[0][0] = 0.0f; CxIm[1][1] = 0.0f; - CxIm[1][0] = hDiracDecBin->ChCrossIm[bin]; - CxIm[0][1] = -hDiracDecBin->ChCrossIm[bin]; + CxIm[1][0] = h->ChCrossIm[bin]; + CxIm[0][1] = -h->ChCrossIm[bin]; /* Make matrix multiplication M*Cx*M' to determine resulting covariance matrix of processing input with M */ matrixMul( Mre, Mim, CxRe, CxIm, tmpMtxRe, tmpMtxIm ); @@ -1315,30 +1420,30 @@ static void ivas_dirac_dec_binaural_determine_processing_matrices( /* Subtract the resulting covariance matrix from the target covariance matrix to determine * what signal component is missing. The result is the target covariance matrix for the residual signal, i.e., * a residual covariance matrix. */ - CrEneL = max( 0.0f, hDiracDecBin->ChEneOut[0][bin] - resultMtxRe[0][0] ); - CrEneR = max( 0.0f, hDiracDecBin->ChEneOut[1][bin] - resultMtxRe[1][1] ); - CrCrossRe = hDiracDecBin->ChCrossReOut[bin] - resultMtxRe[1][0]; - CrCrossIm = hDiracDecBin->ChCrossImOut[bin] - resultMtxIm[1][0]; + CrEneL = max( 0.0f, h->ChEneOut[0][bin] - resultMtxRe[0][0] ); + CrEneR = max( 0.0f, h->ChEneOut[1][bin] - resultMtxRe[1][1] ); + CrCrossRe = h->ChCrossReOut[bin] - resultMtxRe[1][0]; + CrCrossIm = h->ChCrossImOut[bin] - resultMtxIm[1][0]; /* The amount of the decorrelated sound is further controlled based on the spatial metadata, * by determining an energy-suppressed residual covariance matrix that is a control parameter * that guides the processing of the decorrelated sound to a residual signal. * The procedure improves quality in e.g. double-talk 2-direction rendering situations.*/ - if ( ivas_format == MASA_FORMAT && ivas_total_brate < MASA_STEREO_MIN_BITRATE ) + if ( st_ivas->ivas_format == MASA_FORMAT && st_ivas->hDecoderConfig->ivas_total_brate < MASA_STEREO_MIN_BITRATE ) { decorrelationReductionFactor = 1.0f; } - else if ( ( ivas_format == MC_FORMAT && mc_mode == MC_MODE_MCMASA ) || ( ivas_format == MASA_FORMAT && nchan_transport == 1 ) ) + else if ( ( st_ivas->ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCMASA ) || ( st_ivas->ivas_format == MASA_FORMAT && st_ivas->nchan_transport == 1 ) ) { - decorrelationReductionFactor = sqrtf( fmaxf( 0.0f, hDiracDecBin->frameMeanDiffuseness[bin] ) ); + decorrelationReductionFactor = sqrtf( fmaxf( 0.0f, h->frameMeanDiffuseness[bin] ) ); } - else if ( ivas_format == SBA_FORMAT && nchan_transport == 1 ) + else if ( st_ivas->ivas_format == SBA_FORMAT && st_ivas->nchan_transport == 1 ) { decorrelationReductionFactor = 1.0f; } else { - decorrelationReductionFactor = fmaxf( 0.0f, hDiracDecBin->frameMeanDiffuseness[bin] ); + decorrelationReductionFactor = fmaxf( 0.0f, h->frameMeanDiffuseness[bin] ); } CrEneL *= decorrelationReductionFactor; CrEneR *= decorrelationReductionFactor; @@ -1347,7 +1452,7 @@ static void ivas_dirac_dec_binaural_determine_processing_matrices( /* Determine a residual mixing matrix Mdec for processing the decorrelated signal to obtain * the residual signal (that has the residual covariance matrix) */ - formulate2x2MixingMatrix( hDiracDecBin->ChEne[0][bin], hDiracDecBin->ChEne[1][bin], + formulate2x2MixingMatrix( h->ChEne[0][bin], h->ChEne[1][bin], 0.0f, 0.0f, /* Decorrelated signal has ideally no cross-terms */ CrEneL, CrEneR, CrCrossRe, CrCrossIm, @@ -1364,7 +1469,7 @@ static void ivas_dirac_dec_binaural_determine_processing_matrices( /* The regularizations at determining mixing matrices cause signal energy to be lost to some degree, which is compensated for here */ realizedOutputEne = CrEneL + CrEneR + resultMtxRe[0][0] + resultMtxRe[1][1]; - targetOutputEne = hDiracDecBin->ChEneOut[0][bin] + hDiracDecBin->ChEneOut[1][bin]; + targetOutputEne = h->ChEneOut[0][bin] + h->ChEneOut[1][bin]; missingOutputEne = fmaxf( 0.0f, targetOutputEne - realizedOutputEne ); gain = sqrtf( ( resultMtxRe[0][0] + resultMtxRe[1][1] + missingOutputEne ) / @@ -1385,15 +1490,15 @@ static void ivas_dirac_dec_binaural_determine_processing_matrices( { for ( chB = 0; chB < BINAURAL_CHANNELS; chB++ ) { - hDiracDecBin->processMtxRePrev[chA][chB][bin] = hDiracDecBin->processMtxRe[chA][chB][bin]; - hDiracDecBin->processMtxImPrev[chA][chB][bin] = hDiracDecBin->processMtxIm[chA][chB][bin]; - hDiracDecBin->processMtxDecRePrev[chA][chB][bin] = hDiracDecBin->processMtxDecRe[chA][chB][bin]; - hDiracDecBin->processMtxDecImPrev[chA][chB][bin] = hDiracDecBin->processMtxDecIm[chA][chB][bin]; - - hDiracDecBin->processMtxRe[chA][chB][bin] = Mre[chA][chB]; - hDiracDecBin->processMtxIm[chA][chB][bin] = Mim[chA][chB]; - hDiracDecBin->processMtxDecRe[chA][chB][bin] = MdecRe[chA][chB]; - hDiracDecBin->processMtxDecIm[chA][chB][bin] = MdecIm[chA][chB]; + h->processMtxRePrev[chA][chB][bin] = h->processMtxRe[chA][chB][bin]; + h->processMtxImPrev[chA][chB][bin] = h->processMtxIm[chA][chB][bin]; + h->processMtxDecRePrev[chA][chB][bin] = h->processMtxDecRe[chA][chB][bin]; + h->processMtxDecImPrev[chA][chB][bin] = h->processMtxDecIm[chA][chB][bin]; + + h->processMtxRe[chA][chB][bin] = Mre[chA][chB]; + h->processMtxIm[chA][chB][bin] = Mim[chA][chB]; + h->processMtxDecRe[chA][chB][bin] = MdecRe[chA][chB]; + h->processMtxDecIm[chA][chB][bin] = MdecIm[chA][chB]; } } @@ -1405,20 +1510,72 @@ static void ivas_dirac_dec_binaural_determine_processing_matrices( float gainFactor; int16_t aziDeg = 0; int16_t eleDeg = 0; +#ifdef MASA_AND_OBJECTS + uint8_t instantChange = 0; + + if ( st_ivas->ivas_format == MASA_ISM_FORMAT ) + { + gainFactor = 0.7943f * sqrtf( h->earlyPartEneCorrection[bin] ); /* Todo Nokia: Temporary gain for roughly matching the loudness of other processing paths. */ + } + else + { + gainFactor = 0.8414f * sqrtf( h->earlyPartEneCorrection[bin] ); + } + + for ( chB = 0; chB < nchanSeparateChannels; chB++ ) + { + if ( st_ivas->ivas_format == MASA_ISM_FORMAT ) + { + if ( st_ivas->ism_mode == ISM_MASA_MODE_DISC ) + { + aziDeg = st_ivas->hMasaIsmData->azimuth_ism[chB][dirac_read_idx]; + eleDeg = st_ivas->hMasaIsmData->elevation_ism[chB][dirac_read_idx]; + } + else + { + aziDeg = st_ivas->hMasaIsmData->azimuth_separated_ism[dirac_read_idx]; + eleDeg = st_ivas->hMasaIsmData->elevation_separated_ism[dirac_read_idx]; + instantChange = 1; + } + } + + for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ ) + { + h->processMtxRePrev[chA][chB + 2][bin] = h->processMtxRe[chA][chB + 2][bin]; + h->processMtxImPrev[chA][chB + 2][bin] = h->processMtxIm[chA][chB + 2][bin]; + } + + getDirectPartGains( bin, aziDeg, eleDeg, &lRealp, &lImagp, &rRealp, &rImagp, h->renderStereoOutputInsteadOfBinaural, Rmat, &gainCache[chB], isHeadtracked ); - gainFactor = 0.8414f * sqrtf( hDiracDecBin->earlyPartEneCorrection[bin] ); + h->processMtxRe[0][chB + 2][bin] = lRealp * gainFactor; + h->processMtxIm[0][chB + 2][bin] = lImagp * gainFactor; + h->processMtxRe[1][chB + 2][bin] = rRealp * gainFactor; + h->processMtxIm[1][chB + 2][bin] = rImagp * gainFactor; + + if ( instantChange ) + { + for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ ) + { + h->processMtxRePrev[chA][chB + 2][bin] = h->processMtxRe[chA][chB + 2][bin]; + h->processMtxImPrev[chA][chB + 2][bin] = h->processMtxIm[chA][chB + 2][bin]; + } + } + } +#else + gainFactor = 0.8414f * sqrtf( h->earlyPartEneCorrection[bin] ); for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ ) { - hDiracDecBin->processMtxRePrev[chA][2][bin] = hDiracDecBin->processMtxRe[chA][2][bin]; - hDiracDecBin->processMtxImPrev[chA][2][bin] = hDiracDecBin->processMtxIm[chA][2][bin]; + h->processMtxRePrev[chA][2][bin] = h->processMtxRe[chA][2][bin]; + h->processMtxImPrev[chA][2][bin] = h->processMtxIm[chA][2][bin]; } - getDirectPartGains( bin, aziDeg, eleDeg, &lRealp, &lImagp, &rRealp, &rImagp, hDiracDecBin->renderStereoOutputInsteadOfBinaural, Rmat, &gainCache, isHeadtracked ); + getDirectPartGains( bin, aziDeg, eleDeg, &lRealp, &lImagp, &rRealp, &rImagp, h->renderStereoOutputInsteadOfBinaural, Rmat, &gainCache, isHeadtracked ); - hDiracDecBin->processMtxRe[0][2][bin] = lRealp * gainFactor; - hDiracDecBin->processMtxIm[0][2][bin] = lImagp * gainFactor; - hDiracDecBin->processMtxRe[1][2][bin] = rRealp * gainFactor; - hDiracDecBin->processMtxIm[1][2][bin] = rImagp * gainFactor; + h->processMtxRe[0][2][bin] = lRealp * gainFactor; + h->processMtxIm[0][2][bin] = lImagp * gainFactor; + h->processMtxRe[1][2][bin] = rRealp * gainFactor; + h->processMtxIm[1][2][bin] = rImagp * gainFactor; +#endif } } @@ -1427,15 +1584,12 @@ static void ivas_dirac_dec_binaural_determine_processing_matrices( static void ivas_dirac_dec_binaural_process_output( - DIRAC_DEC_BIN_HANDLE hDiracDecBin, - SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, - HANDLE_CLDFB_FILTER_BANK cldfbSynDec[MAX_OUTPUT_CHANNELS], + Decoder_Struct *st_ivas, float *output_f[], float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], const int16_t max_band_decorr, const int16_t numInChannels, - const int16_t processReverb, const int16_t subframe ) { int16_t slot, bin, chA, chB; @@ -1444,29 +1598,31 @@ static void ivas_dirac_dec_binaural_process_output( float decSlotRe[BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX], decSlotIm[BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX]; float reverbRe[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; float reverbIm[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + DIRAC_DEC_BIN_HANDLE h; float interpVal; float *decSlotRePointer; float *decSlotImPointer; int16_t offsetSamples; int16_t nSlots; - nBins = hSpatParamRendCom->num_freq_bands; + h = st_ivas->hDiracDecBin; + nBins = st_ivas->hDirAC->num_freq_bands; offsetSamples = 0; - nSlots = hSpatParamRendCom->subframe_nbslots[subframe]; + nSlots = st_ivas->hDirAC->subframe_nbslots[subframe]; - if ( processReverb ) + if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) { /* Process second / room effect part of binaural output when needed */ - ivas_binaural_reverb_processSubframe( hDiracDecBin->hReverb, numInChannels, nSlots, inRe, inIm, reverbRe, reverbIm ); + ivas_binaural_reverb_processSubframe( st_ivas->hDiracDecBin->hReverb, numInChannels, nSlots, inRe, inIm, reverbRe, reverbIm ); } interpVal = 0.0f; for ( slot = 0; slot < nSlots; slot++ ) { interpVal += 1.0f / (float) nSlots; - if ( !hDiracDecBin->useTdDecorr && max_band_decorr > 0 ) + if ( !st_ivas->hDiracDecBin->useTdDecorr && max_band_decorr > 0 ) { - ivas_dirac_dec_decorrelate_slot( hDiracDecBin, nBins, slot, inRe, inIm, decSlotRe, decSlotIm ); + ivas_dirac_dec_decorrelate_slot( st_ivas->hDirAC, slot, inRe, inIm, decSlotRe, decSlotIm ); } for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ ) @@ -1479,7 +1635,7 @@ static void ivas_dirac_dec_binaural_process_output( /* Processing of the first / HRTF part of the binaural output. */ for ( chB = 0; chB < numInChannels; chB++ ) { - if ( hDiracDecBin->useTdDecorr ) + if ( st_ivas->hDiracDecBin->useTdDecorr ) { decSlotRePointer = inRe[chB + 2][slot]; decSlotImPointer = inIm[chB + 2][slot]; @@ -1495,33 +1651,33 @@ static void ivas_dirac_dec_binaural_process_output( float gain; /* Mixing using the formulated processing matrix M */ - gain = ( 1.0f - interpVal ) * hDiracDecBin->processMtxRePrev[chA][chB][bin] + - interpVal * hDiracDecBin->processMtxRe[chA][chB][bin]; + gain = ( 1.0f - interpVal ) * h->processMtxRePrev[chA][chB][bin] + + interpVal * h->processMtxRe[chA][chB][bin]; outSlotRe[bin] += gain * inRe[chB][slot][bin]; outSlotIm[bin] += gain * inIm[chB][slot][bin]; - gain = ( 1.0f - interpVal ) * hDiracDecBin->processMtxImPrev[chA][chB][bin] + - interpVal * hDiracDecBin->processMtxIm[chA][chB][bin]; + gain = ( 1.0f - interpVal ) * h->processMtxImPrev[chA][chB][bin] + + interpVal * h->processMtxIm[chA][chB][bin]; outSlotRe[bin] -= gain * inIm[chB][slot][bin]; outSlotIm[bin] += gain * inRe[chB][slot][bin]; /* Mixing decorrelated signals using the formulated residual processing matrix Mdec */ if ( bin < max_band_decorr && chB < 2 ) { - gain = ( 1.0f - interpVal ) * hDiracDecBin->processMtxDecRePrev[chA][chB][bin] + - interpVal * hDiracDecBin->processMtxDecRe[chA][chB][bin]; + gain = ( 1.0f - interpVal ) * h->processMtxDecRePrev[chA][chB][bin] + + interpVal * h->processMtxDecRe[chA][chB][bin]; outSlotRe[bin] += gain * decSlotRePointer[bin]; outSlotIm[bin] += gain * decSlotImPointer[bin]; - gain = ( 1.0f - interpVal ) * hDiracDecBin->processMtxDecImPrev[chA][chB][bin] + - interpVal * hDiracDecBin->processMtxDecIm[chA][chB][bin]; + gain = ( 1.0f - interpVal ) * h->processMtxDecImPrev[chA][chB][bin] + + interpVal * h->processMtxDecIm[chA][chB][bin]; outSlotRe[bin] -= gain * decSlotImPointer[bin]; outSlotIm[bin] += gain * decSlotRePointer[bin]; } } } - if ( processReverb ) + if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) { /* Combine second (reverb) part with the first (HRTF) part to obtain binaural output signal with room effect */ v_add( outSlotRe, reverbRe[chA][slot], outSlotRe, CLDFB_NO_CHANNELS_MAX ); @@ -1532,7 +1688,7 @@ static void ivas_dirac_dec_binaural_process_output( outSlotImPr = &( outSlotIm[0] ); /* Inverse filter bank */ - cldfbSynthesis( &outSlotRePr, &outSlotImPr, &( output_f[chA][nBins * slot + offsetSamples] ), nBins, cldfbSynDec[chA] ); + cldfbSynthesis( &outSlotRePr, &outSlotImPr, &( output_f[chA][nBins * slot + offsetSamples] ), nBins, st_ivas->cldfbSynDec[chA] ); } } @@ -2209,10 +2365,7 @@ static void hrtfShGetHrtf( { float shVec[HRTF_SH_CHANNELS]; - ivas_dirac_dec_get_response( aziDeg, - eleDeg, - shVec, - HRTF_SH_ORDER ); + ivas_dirac_dec_get_response( aziDeg, eleDeg, shVec, HRTF_SH_ORDER ); for ( k = 0; k < HRTF_SH_CHANNELS; k++ ) { @@ -2243,6 +2396,7 @@ float configure_reqularization_factor( ) { float reqularizationFactor; + reqularizationFactor = 1.0f; /* Default value */ if ( ivas_format == MASA_FORMAT ) @@ -2293,7 +2447,236 @@ float configure_reqularization_factor( } } - /* For SBA and parametric ISM, currently in default value of 1.0f. */ + /* For SBA and parametric ISM, default value of 1.0f. */ return reqularizationFactor; } + + +#ifdef MASA_AND_OBJECTS +/*-------------------------------------------------------------------* + * preProcessStereoTransportsForMovedObjects() + * + * + *-------------------------------------------------------------------*/ +// Todo OMASA JBM: This might need further adjustments +void preProcessStereoTransportsForMovedObjects( + Decoder_Struct *st_ivas, + float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], + float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], + const int16_t nBins, + const int16_t subframe ) +{ + int16_t bin, ch, inCh, outCh, ismDirIndex, slot; + DIRAC_DEC_HANDLE hDirAC; + MASA_ISM_DATA_HANDLE hMasaIsmData; + uint8_t enableCentering; + int16_t dirac_read_idx; + int16_t nSlots; + + hDirAC = st_ivas->hDirAC; + hMasaIsmData = st_ivas->hMasaIsmData; + + if ( st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_FOA || st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_HOA2 || st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_HOA3 ) + { + enableCentering = 0; + } + else + { + enableCentering = 1; + } + + /* Bypass processing until first object is moved */ + if ( hMasaIsmData->objectsMoved == 0 ) + { + for ( ismDirIndex = 0; ismDirIndex < hDirAC->numIsmDirections; ismDirIndex++ ) + { + if ( hMasaIsmData->ism_is_edited[ismDirIndex] ) + { + hMasaIsmData->objectsMoved = 1; + } + } + if ( hMasaIsmData->objectsMoved == 0 ) + { + /* No objects have moved so far */ + return; + } + } + + /* Perform object-movement based processing */ + // Todo OMASA JBM: Fixed but might be still wrong somehow + nSlots = st_ivas->hDirAC->subframe_nbslots[subframe]; + dirac_read_idx = st_ivas->hDirAC->render_to_md_map[subframe]; + + for ( bin = 0; bin < nBins; bin++ ) + { + float ismPreprocMtxNew[2][2]; + float ismPreprocMtxIncrement[2][2]; + float eneMove[2]; + float enePreserve[2]; + float ismRatioAcc; + float subframeEne; + float normEnes[2]; + float remainderNormEne; + + set_zero( ismPreprocMtxNew[0], 2 ); + set_zero( ismPreprocMtxNew[1], 2 ); + set_zero( ismPreprocMtxIncrement[0], 2 ); + set_zero( ismPreprocMtxIncrement[1], 2 ); + set_zero( eneMove, 2 ); + set_zero( enePreserve, 2 ); + ismRatioAcc = 0.0f; + subframeEne = 0.0f; + set_zero( normEnes, 2 ); + + /* Determine transport normalized energies and subframe energy */ + for ( slot = 0; slot < nSlots; slot++ ) + { + for ( ch = 0; ch < 2; ch++ ) + { + normEnes[ch] += inRe[ch][slot][bin] * inRe[ch][slot][bin]; + normEnes[ch] += inIm[ch][slot][bin] * inIm[ch][slot][bin]; + } + } + subframeEne = normEnes[0] + normEnes[1]; + normEnes[0] /= fmaxf( 1e-12f, subframeEne ); + normEnes[1] /= fmaxf( 1e-12f, subframeEne ); + + /* For each ismDir, formulate a mix-matrix that moves object audio signals between + * left and right channels when needed. Make a combined matrix by a ratio-weighted sum */ + for ( ismDirIndex = 0; ismDirIndex < hDirAC->numIsmDirections; ismDirIndex++ ) + { + float panGainsOut[2]; + float panGainsIn[2]; + float ratio; + float panEnesOut[2]; + float panEnesIn[2]; + float centeringFactor; + + ratio = hMasaIsmData->energy_ratio_ism[ismDirIndex][dirac_read_idx][bin]; + + ismRatioAcc += ratio; + + /* Get input and output panning gains */ + ivas_get_stereo_panning_gains( hMasaIsmData->azimuth_ism[ismDirIndex][dirac_read_idx], + hMasaIsmData->elevation_ism[ismDirIndex][dirac_read_idx], + panGainsIn ); + + if ( hMasaIsmData->ism_is_edited[ismDirIndex] ) + { + ivas_get_stereo_panning_gains( hMasaIsmData->azimuth_ism_edited[ismDirIndex], + hMasaIsmData->elevation_ism_edited[ismDirIndex], + panGainsOut ); + } + else + { + /* When not edited, input and output pan gains are the same */ + for ( ch = 0; ch < 2; ch++ ) + { + panGainsOut[ch] = panGainsIn[ch]; + } + } + + /* Determine pan enes */ + for ( ch = 0; ch < 2; ch++ ) + { + panEnesOut[ch] = panGainsOut[ch] * panGainsOut[ch]; + panEnesIn[ch] = panGainsIn[ch] * panGainsIn[ch]; + } + + if ( enableCentering ) + { + centeringFactor = fmaxf( 0.0f, 2.0f * fabsf( panEnesIn[0] - panEnesOut[0] ) - 1.0f ); + for ( ch = 0; ch < 2; ch++ ) + { + panEnesOut[ch] *= ( 1.0f - centeringFactor ); + panEnesOut[ch] += 0.5f * centeringFactor; + } + } + + for ( ch = 0; ch < 2; ch++ ) + { + float eneMoveThis; + float enePreserveThis; + eneMoveThis = fmaxf( 0.0f, panEnesIn[ch] - panEnesOut[ch] ); + enePreserveThis = panEnesIn[ch] - eneMoveThis; + + eneMove[ch] += ratio * eneMoveThis; + enePreserve[ch] += ratio * enePreserveThis; + + /* Subtract object parts from normEnes */ + normEnes[ch] -= panEnesIn[ch] * ratio; + } + } + + /* Any remaining (non-object) energy is set to be preserved at both channels */ + remainderNormEne = fmaxf( 0.0f, ( 1.0f - ismRatioAcc ) - normEnes[0] - normEnes[1] ); + for ( ch = 0; ch < 2; ch++ ) + { + enePreserve[ch] += fmaxf( 0.0f, normEnes[ch] + remainderNormEne / 2.0f ); + } + + /* Temporally average energy moving and preserving, and generate the transport signal preprocessing matrix */ + for ( ch = 0; ch < 2; ch++ ) + { + float normVal; + hMasaIsmData->eneMoveIIR[ch][bin] *= STEREO_PREPROCESS_IIR_FACTOR; + hMasaIsmData->eneMoveIIR[ch][bin] += eneMove[ch] * subframeEne; + hMasaIsmData->enePreserveIIR[ch][bin] *= STEREO_PREPROCESS_IIR_FACTOR; + hMasaIsmData->enePreserveIIR[ch][bin] += enePreserve[ch] * subframeEne; + normVal = fmaxf( EPSILON, hMasaIsmData->eneMoveIIR[ch][bin] + hMasaIsmData->enePreserveIIR[ch][bin] ); + ismPreprocMtxNew[ch][ch] = sqrtf( hMasaIsmData->enePreserveIIR[ch][bin] / normVal ); + ismPreprocMtxNew[1 - ch][ch] = sqrtf( hMasaIsmData->eneMoveIIR[ch][bin] / normVal ); + } + + /* Get increment value for temporal interpolation */ + for ( inCh = 0; inCh < 2; inCh++ ) + { + for ( outCh = 0; outCh < 2; outCh++ ) + { + ismPreprocMtxIncrement[outCh][inCh] = ( ismPreprocMtxNew[outCh][inCh] - hMasaIsmData->ismPreprocMatrix[outCh][inCh][bin] ) / (float) nSlots; + } + } + + /* Mix signals */ + for ( slot = 0; slot < nSlots; slot++ ) + { + float eqVal; + float outSlotRe[2]; + float outSlotIm[2]; + + set_zero( outSlotRe, 2 ); + set_zero( outSlotIm, 2 ); + + for ( outCh = 0; outCh < 2; outCh++ ) + { + for ( inCh = 0; inCh < 2; inCh++ ) + { + hMasaIsmData->ismPreprocMatrix[outCh][inCh][bin] += ismPreprocMtxIncrement[outCh][inCh]; + outSlotRe[outCh] += inRe[inCh][slot][bin] * hMasaIsmData->ismPreprocMatrix[outCh][inCh][bin]; + outSlotIm[outCh] += inIm[inCh][slot][bin] * hMasaIsmData->ismPreprocMatrix[outCh][inCh][bin]; + } + } + + /* IIR average the energy measures and determine and apply energy-preserving equalizer */ + hMasaIsmData->preprocEneTarget[bin] *= STEREO_PREPROCESS_IIR_FACTOR; + hMasaIsmData->preprocEneRealized[bin] *= STEREO_PREPROCESS_IIR_FACTOR; + for ( ch = 0; ch < 2; ch++ ) + { + hMasaIsmData->preprocEneTarget[bin] += inRe[ch][slot][bin] * inRe[ch][slot][bin]; + hMasaIsmData->preprocEneTarget[bin] += inIm[ch][slot][bin] * inIm[ch][slot][bin]; + hMasaIsmData->preprocEneRealized[bin] += outSlotRe[ch] * outSlotRe[ch]; + hMasaIsmData->preprocEneRealized[bin] += outSlotIm[ch] * outSlotIm[ch]; + } + eqVal = fminf( 4.0f, sqrtf( hMasaIsmData->preprocEneTarget[bin] / fmaxf( 1e-12f, hMasaIsmData->preprocEneRealized[bin] ) ) ); + for ( ch = 0; ch < 2; ch++ ) + { + inRe[ch][slot][bin] = outSlotRe[ch] * eqVal; + inIm[ch][slot][bin] = outSlotIm[ch] * eqVal; + } + } + } + + return; +} +#endif diff --git a/lib_rend/ivas_dirac_rend.c b/lib_rend/ivas_dirac_rend.c deleted file mode 100644 index 84ce30d1bce60f83798b233d2c0286ef559c9e73..0000000000000000000000000000000000000000 --- a/lib_rend/ivas_dirac_rend.c +++ /dev/null @@ -1,2030 +0,0 @@ -/****************************************************************************************************** - -(C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, -Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., -Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, -Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other -contributors to this repository. All Rights Reserved. - -This software is protected by copyright law and by international treaties. -The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, -Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., -Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, -Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other -contributors to this repository retain full ownership rights in their respective contributions in -the software. This notice grants no license of any kind, including but not limited to patent -license, nor is any license granted by implication, estoppel or otherwise. - -Contributors are required to enter into the IVAS codec Public Collaboration agreement before making -contributions. - -This software is provided "AS IS", without any express or implied warranties. The software is in the -development stage. It is intended exclusively for experts who have experience with such software and -solely for the purpose of inspection. All implied warranties of non-infringement, merchantability -and fitness for a particular purpose are hereby disclaimed and excluded. - -Any dispute, controversy or claim arising under or in relation to providing this software shall be -submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in -accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and -the United Nations Convention on Contracts on the International Sales of Goods. - -*******************************************************************************************************/ - -#include -#include -#include "options.h" -#include -#include "cnst.h" -#include "prot.h" -#include "ivas_prot.h" -#include "ivas_prot_rend.h" -#include "ivas_cnst.h" -#include "ivas_rom_dec.h" -#ifdef DEBUGGING -#include "debug.h" -#endif -#include "wmc_auto.h" - - -/*------------------------------------------------------------------------- - * ivas_dirac_allocate_parameters() - * - * Allocate and initialize DirAC parameters - *-------------------------------------------------------------------------*/ - -ivas_error ivas_dirac_allocate_parameters( - SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, /* i/o: common data for spatial parametric rendering */ - const int16_t params_flag /* i : set of parameters flag */ -) -{ - int16_t i; - - if ( params_flag == 1 ) - { - if ( ( hSpatParamRendCom->azimuth = (int16_t **) malloc( hSpatParamRendCom->dirac_md_buffer_length * sizeof( int16_t * ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); - } - - if ( ( hSpatParamRendCom->elevation = (int16_t **) malloc( hSpatParamRendCom->dirac_md_buffer_length * sizeof( int16_t * ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); - } - - if ( ( hSpatParamRendCom->diffuseness_vector = (float **) malloc( hSpatParamRendCom->dirac_md_buffer_length * sizeof( float * ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); - } - - if ( ( hSpatParamRendCom->energy_ratio1 = (float **) malloc( hSpatParamRendCom->dirac_md_buffer_length * sizeof( float * ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); - } - - if ( ( hSpatParamRendCom->spreadCoherence = (float **) malloc( hSpatParamRendCom->dirac_md_buffer_length * sizeof( float * ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); - } - - if ( ( hSpatParamRendCom->surroundingCoherence = (float **) malloc( hSpatParamRendCom->dirac_md_buffer_length * sizeof( float * ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); - } - - for ( i = 0; i < hSpatParamRendCom->dirac_md_buffer_length; i++ ) - { - if ( ( hSpatParamRendCom->azimuth[i] = (int16_t *) malloc( hSpatParamRendCom->num_freq_bands * sizeof( int16_t ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); - } - set_s( hSpatParamRendCom->azimuth[i], 0, hSpatParamRendCom->num_freq_bands ); - - if ( ( hSpatParamRendCom->elevation[i] = (int16_t *) malloc( hSpatParamRendCom->num_freq_bands * sizeof( int16_t ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); - } - set_s( hSpatParamRendCom->elevation[i], 0, hSpatParamRendCom->num_freq_bands ); - - if ( ( hSpatParamRendCom->diffuseness_vector[i] = (float *) malloc( hSpatParamRendCom->num_freq_bands * sizeof( float ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); - } - set_f( hSpatParamRendCom->diffuseness_vector[i], 1.0f, hSpatParamRendCom->num_freq_bands ); - - if ( ( hSpatParamRendCom->energy_ratio1[i] = (float *) malloc( hSpatParamRendCom->num_freq_bands * sizeof( float ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); - } - set_f( hSpatParamRendCom->energy_ratio1[i], 0.0f, hSpatParamRendCom->num_freq_bands ); - - if ( ( hSpatParamRendCom->spreadCoherence[i] = (float *) malloc( hSpatParamRendCom->num_freq_bands * sizeof( float ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); - } - set_f( hSpatParamRendCom->spreadCoherence[i], 0.0f, hSpatParamRendCom->num_freq_bands ); - - if ( ( hSpatParamRendCom->surroundingCoherence[i] = (float *) malloc( hSpatParamRendCom->num_freq_bands * sizeof( float ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); - } - set_f( hSpatParamRendCom->surroundingCoherence[i], 0.0f, hSpatParamRendCom->num_freq_bands ); - } - } - else if ( params_flag == 2 ) - { - if ( ( hSpatParamRendCom->azimuth2 = (int16_t **) malloc( hSpatParamRendCom->dirac_md_buffer_length * sizeof( int16_t * ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); - } - - if ( ( hSpatParamRendCom->elevation2 = (int16_t **) malloc( hSpatParamRendCom->dirac_md_buffer_length * sizeof( int16_t * ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); - } - - if ( ( hSpatParamRendCom->energy_ratio2 = (float **) malloc( hSpatParamRendCom->dirac_md_buffer_length * sizeof( float * ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); - } - - if ( ( hSpatParamRendCom->spreadCoherence2 = (float **) malloc( hSpatParamRendCom->dirac_md_buffer_length * sizeof( float * ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); - } - - for ( i = 0; i < hSpatParamRendCom->dirac_md_buffer_length; i++ ) - { - if ( ( hSpatParamRendCom->azimuth2[i] = (int16_t *) malloc( hSpatParamRendCom->num_freq_bands * sizeof( int16_t ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); - } - set_s( hSpatParamRendCom->azimuth2[i], 0, hSpatParamRendCom->num_freq_bands ); - - if ( ( hSpatParamRendCom->elevation2[i] = (int16_t *) malloc( hSpatParamRendCom->num_freq_bands * sizeof( int16_t ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); - } - set_s( hSpatParamRendCom->elevation2[i], 0, hSpatParamRendCom->num_freq_bands ); - - if ( ( hSpatParamRendCom->energy_ratio2[i] = (float *) malloc( hSpatParamRendCom->num_freq_bands * sizeof( float ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); - } - set_f( hSpatParamRendCom->energy_ratio2[i], 0.0f, hSpatParamRendCom->num_freq_bands ); - - if ( ( hSpatParamRendCom->spreadCoherence2[i] = (float *) malloc( hSpatParamRendCom->num_freq_bands * sizeof( float ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); - } - set_f( hSpatParamRendCom->spreadCoherence2[i], 0.0f, hSpatParamRendCom->num_freq_bands ); - } - } - - return IVAS_ERR_OK; -} - - -ivas_error ivas_spat_hSpatParamRendCom_config( - SPAT_PARAM_REND_COMMON_DATA_HANDLE *hSpatParamRendCom_out, /* i/o: IVAS decoder structure */ - const DIRAC_CONFIG_FLAG flag_config_inp, /* i/ : Flag determining if we open or reconfigure the DirAC decoder */ - const int16_t dec_param_estim_flag, - const IVAS_FORMAT ivas_format, - const MC_MODE mc_mode, - const int32_t output_Fs, - const int16_t hodirac_flag ) -{ - ivas_error error; - int16_t map_idx; - DIRAC_CONFIG_FLAG flag_config; - SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom; - - flag_config = ( flag_config_inp == DIRAC_RECONFIGURE_MODE ) ? DIRAC_RECONFIGURE : flag_config_inp; - error = IVAS_ERR_OK; - - hSpatParamRendCom = NULL; - - if ( flag_config == DIRAC_RECONFIGURE ) - { - hSpatParamRendCom = *hSpatParamRendCom_out; - } - else if ( flag_config == DIRAC_OPEN ) - { - /*-----------------------------------------------------------------* - * prepare library opening - *-----------------------------------------------------------------*/ - - if ( ( hSpatParamRendCom = (SPAT_PARAM_REND_COMMON_DATA_HANDLE) malloc( sizeof( SPAT_PARAM_REND_COMMON_DATA ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC meta\n" ) ); - } - - *hSpatParamRendCom_out = hSpatParamRendCom; - } - - - if ( flag_config == DIRAC_OPEN ) - { - hSpatParamRendCom->slot_size = (int16_t) ( ( output_Fs / FRAMES_PER_SEC ) / CLDFB_NO_COL_MAX ); - set_s( hSpatParamRendCom->subframe_nbslots, 0, MAX_JBM_SUBFRAMES_5MS ); - set_s( hSpatParamRendCom->subframe_nbslots, JBM_CLDFB_SLOTS_IN_SUBFRAME, DEFAULT_JBM_SUBFRAMES_5MS ); - hSpatParamRendCom->nb_subframes = DEFAULT_JBM_SUBFRAMES_5MS; - hSpatParamRendCom->subframes_rendered = 0; - hSpatParamRendCom->slots_rendered = 0; - hSpatParamRendCom->num_slots = DEFAULT_JBM_SUBFRAMES_5MS * JBM_CLDFB_SLOTS_IN_SUBFRAME; - hSpatParamRendCom->num_freq_bands = (int16_t) ( output_Fs * INV_CLDFB_BANDWIDTH + 0.5f ); - } - - /*-----------------------------------------------------------------* - * set input parameters - *-----------------------------------------------------------------*/ - - if ( ivas_format == SBA_FORMAT && flag_config == DIRAC_RECONFIGURE ) - { - if ( hodirac_flag && hSpatParamRendCom->azimuth2 == NULL ) - { - if ( ( error = ivas_dirac_allocate_parameters( hSpatParamRendCom, 2 ) ) != IVAS_ERR_OK ) - { - return error; - } - } - else if ( !hodirac_flag && hSpatParamRendCom->azimuth2 != NULL ) - { - ivas_dirac_deallocate_parameters( hSpatParamRendCom, 2 ); - } - } - - if ( flag_config == DIRAC_OPEN ) - { - hSpatParamRendCom->dirac_md_buffer_length = 0; - hSpatParamRendCom->dirac_bs_md_write_idx = 0; - hSpatParamRendCom->dirac_read_idx = 0; - if ( mc_mode == MC_MODE_MCMASA ) - { - hSpatParamRendCom->dirac_md_buffer_length = MAX_PARAM_SPATIAL_SUBFRAMES; - - set_s( hSpatParamRendCom->render_to_md_map, 0, MAX_JBM_SUBFRAMES_5MS * JBM_CLDFB_SLOTS_IN_SUBFRAME ); - for ( map_idx = 0; map_idx < DEFAULT_JBM_SUBFRAMES_5MS; map_idx++ ) - { - hSpatParamRendCom->render_to_md_map[map_idx] = map_idx; - } - } - else if ( ivas_format == MASA_FORMAT ) - { - hSpatParamRendCom->dirac_md_buffer_length = MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR; - hSpatParamRendCom->dirac_bs_md_write_idx = DELAY_MASA_PARAM_DEC_SFR; - - set_s( hSpatParamRendCom->render_to_md_map, 0, MAX_JBM_SUBFRAMES_5MS * JBM_CLDFB_SLOTS_IN_SUBFRAME ); - for ( map_idx = 0; map_idx < DEFAULT_JBM_SUBFRAMES_5MS; map_idx++ ) - { - hSpatParamRendCom->render_to_md_map[map_idx] = map_idx; - } - } - else - { - int16_t num_slots_in_subfr; - num_slots_in_subfr = dec_param_estim_flag ? CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES : 1; - hSpatParamRendCom->dirac_md_buffer_length = ( MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_DIRAC_PARAM_DEC_SFR ); - hSpatParamRendCom->dirac_bs_md_write_idx = DELAY_DIRAC_PARAM_DEC_SFR; - hSpatParamRendCom->dirac_read_idx = 0; - - set_s( hSpatParamRendCom->render_to_md_map, 0, MAX_JBM_SUBFRAMES_5MS * JBM_CLDFB_SLOTS_IN_SUBFRAME ); - for ( map_idx = 0; map_idx < DEFAULT_JBM_SUBFRAMES_5MS * num_slots_in_subfr; map_idx++ ) - { - hSpatParamRendCom->render_to_md_map[map_idx] = hSpatParamRendCom->dirac_read_idx + map_idx / num_slots_in_subfr; - } - } - - if ( ( error = ivas_dirac_allocate_parameters( hSpatParamRendCom, 1 ) ) != IVAS_ERR_OK ) - { - return error; - } - - if ( ivas_format == MASA_FORMAT || ( ivas_format == SBA_FORMAT && hodirac_flag ) ) - { - if ( ( error = ivas_dirac_allocate_parameters( hSpatParamRendCom, 2 ) ) != IVAS_ERR_OK ) - { - return error; - } - } - else - { - hSpatParamRendCom->azimuth2 = NULL; - hSpatParamRendCom->elevation2 = NULL; - hSpatParamRendCom->energy_ratio2 = NULL; - hSpatParamRendCom->spreadCoherence2 = NULL; - } - } - - return error; -} - - -void ivas_spat_hSpatParamRendCom_close( - SPAT_PARAM_REND_COMMON_DATA_HANDLE *hSpatParamRendCom_out ) -{ - if ( hSpatParamRendCom_out == NULL || *hSpatParamRendCom_out == NULL ) - { - return; - } - - ivas_dirac_deallocate_parameters( *hSpatParamRendCom_out, 1 ); - ivas_dirac_deallocate_parameters( *hSpatParamRendCom_out, 2 ); - - free( *hSpatParamRendCom_out ); - *hSpatParamRendCom_out = NULL; - - return; -} - -void ivas_dirac_rend_close( - DIRAC_REND_HANDLE *hDirACRend_out ) -{ - int16_t i, j; - DIRAC_REND_HANDLE hDirACRend; - - if ( hDirACRend_out == NULL || *hDirACRend_out == NULL ) - { - return; - } - - hDirACRend = *hDirACRend_out; - - /* close Output synthesis sub-module */ - ivas_dirac_dec_output_synthesis_close( hDirACRend ); - - /* close Decorrelator sub-module */ - if ( hDirACRend->proto_signal_decorr_on ) - { - ivas_dirac_dec_decorr_close( &hDirACRend->h_freq_domain_decorr_ap_params, &hDirACRend->h_freq_domain_decorr_ap_state ); - } - - /* Params */ - - /* free frequency axis buffer */ - if ( hDirACRend->frequency_axis != NULL ) - { - free( hDirACRend->frequency_axis ); - hDirACRend->frequency_axis = NULL; - } - - if ( hDirACRend->diffuse_response_function != NULL ) - { - free( hDirACRend->diffuse_response_function ); - hDirACRend->diffuse_response_function = NULL; - } - - if ( hDirACRend->hoa_encoder != NULL ) - { - free( hDirACRend->hoa_encoder ); - hDirACRend->hoa_encoder = NULL; - } - - /* prototype indexing */ - if ( hDirACRend->proto_index_dir != NULL ) - { - free( hDirACRend->proto_index_dir ); - hDirACRend->proto_index_dir = NULL; - } - - if ( hDirACRend->proto_index_diff != NULL ) - { - free( hDirACRend->proto_index_diff ); - hDirACRend->proto_index_dir = NULL; - } - - /* States */ - - /* free prototype signal buffers */ - if ( hDirACRend->proto_frame_f != NULL ) - { - free( hDirACRend->proto_frame_f ); - hDirACRend->proto_frame_f = NULL; - } - - for ( i = 0; i < DIRAC_NUM_DIMS; i++ ) - { - for ( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ ) - { - if ( hDirACRend->buffer_intensity_real[i][j] != NULL ) - { - free( hDirACRend->buffer_intensity_real[i][j] ); - hDirACRend->buffer_intensity_real[i][j] = NULL; - } - } - } - if ( hDirACRend->buffer_energy != NULL ) - { - free( hDirACRend->buffer_energy ); - hDirACRend->buffer_energy = NULL; - } - - if ( hDirACRend->masa_stereo_type_detect != NULL ) - { - free( hDirACRend->masa_stereo_type_detect ); - hDirACRend->masa_stereo_type_detect = NULL; - } - - ivas_dirac_free_mem( &( hDirACRend->stack_mem ) ); - - free( *hDirACRend_out ); - *hDirACRend_out = NULL; - - return; -} - - -/*------------------------------------------------------------------------- - * ivas_dirac_deallocate_parameters() - * - * Deallocate DirAC parameters - *-------------------------------------------------------------------------*/ - -void ivas_dirac_deallocate_parameters( - SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, /* i/o: common data for spatial parametric rendering */ - const int16_t params_flag /* i : set of parameters flag */ -) -{ - int16_t i; - int16_t md_buffer_length; - - if ( hSpatParamRendCom == NULL ) - { - return; - } - - md_buffer_length = hSpatParamRendCom->dirac_md_buffer_length; - - if ( params_flag == 1 ) - { - if ( hSpatParamRendCom->azimuth != NULL ) - { - for ( i = 0; i < md_buffer_length; i++ ) - { - if ( hSpatParamRendCom->azimuth[i] != NULL ) - { - free( hSpatParamRendCom->azimuth[i] ); - hSpatParamRendCom->azimuth[i] = NULL; - } - } - - free( hSpatParamRendCom->azimuth ); - hSpatParamRendCom->azimuth = NULL; - } - - if ( hSpatParamRendCom->elevation != NULL ) - { - for ( i = 0; i < md_buffer_length; i++ ) - { - if ( hSpatParamRendCom->elevation[i] != NULL ) - { - free( hSpatParamRendCom->elevation[i] ); - hSpatParamRendCom->elevation[i] = NULL; - } - } - - free( hSpatParamRendCom->elevation ); - hSpatParamRendCom->elevation = NULL; - } - - if ( hSpatParamRendCom->energy_ratio1 != NULL ) - { - for ( i = 0; i < md_buffer_length; i++ ) - { - if ( hSpatParamRendCom->energy_ratio1[i] != NULL ) - { - free( hSpatParamRendCom->energy_ratio1[i] ); - hSpatParamRendCom->energy_ratio1[i] = NULL; - } - } - free( hSpatParamRendCom->energy_ratio1 ); - hSpatParamRendCom->energy_ratio1 = NULL; - } - - if ( hSpatParamRendCom->diffuseness_vector != NULL ) - { - for ( i = 0; i < md_buffer_length; i++ ) - { - if ( hSpatParamRendCom->diffuseness_vector[i] != NULL ) - { - free( hSpatParamRendCom->diffuseness_vector[i] ); - hSpatParamRendCom->diffuseness_vector[i] = NULL; - } - } - - free( hSpatParamRendCom->diffuseness_vector ); - hSpatParamRendCom->diffuseness_vector = NULL; - } - - if ( hSpatParamRendCom->spreadCoherence != NULL ) - { - for ( i = 0; i < md_buffer_length; i++ ) - { - if ( hSpatParamRendCom->spreadCoherence[i] != NULL ) - { - free( hSpatParamRendCom->spreadCoherence[i] ); - hSpatParamRendCom->spreadCoherence[i] = NULL; - } - } - free( hSpatParamRendCom->spreadCoherence ); - hSpatParamRendCom->spreadCoherence = NULL; - } - - if ( hSpatParamRendCom->surroundingCoherence != NULL ) - { - for ( i = 0; i < md_buffer_length; i++ ) - { - if ( hSpatParamRendCom->surroundingCoherence[i] != NULL ) - { - free( hSpatParamRendCom->surroundingCoherence[i] ); - hSpatParamRendCom->surroundingCoherence[i] = NULL; - } - } - free( hSpatParamRendCom->surroundingCoherence ); - hSpatParamRendCom->surroundingCoherence = NULL; - } - } - else if ( params_flag == 2 ) - { - if ( hSpatParamRendCom->azimuth2 != NULL ) - { - for ( i = 0; i < md_buffer_length; i++ ) - { - if ( hSpatParamRendCom->azimuth2[i] != NULL ) - { - free( hSpatParamRendCom->azimuth2[i] ); - hSpatParamRendCom->azimuth2[i] = NULL; - } - } - free( hSpatParamRendCom->azimuth2 ); - hSpatParamRendCom->azimuth2 = NULL; - } - - if ( hSpatParamRendCom->elevation2 != NULL ) - { - for ( i = 0; i < md_buffer_length; i++ ) - { - if ( hSpatParamRendCom->elevation2[i] != NULL ) - { - free( hSpatParamRendCom->elevation2[i] ); - hSpatParamRendCom->elevation2[i] = NULL; - } - } - free( hSpatParamRendCom->elevation2 ); - hSpatParamRendCom->elevation2 = NULL; - } - - if ( hSpatParamRendCom->energy_ratio2 != NULL ) - { - for ( i = 0; i < md_buffer_length; i++ ) - { - if ( hSpatParamRendCom->energy_ratio2[i] != NULL ) - { - free( hSpatParamRendCom->energy_ratio2[i] ); - hSpatParamRendCom->energy_ratio2[i] = NULL; - } - } - free( hSpatParamRendCom->energy_ratio2 ); - hSpatParamRendCom->energy_ratio2 = NULL; - } - - if ( hSpatParamRendCom->spreadCoherence2 != NULL ) - { - for ( i = 0; i < md_buffer_length; i++ ) - { - if ( hSpatParamRendCom->spreadCoherence2[i] != NULL ) - { - free( hSpatParamRendCom->spreadCoherence2[i] ); - hSpatParamRendCom->spreadCoherence2[i] = NULL; - } - } - free( hSpatParamRendCom->spreadCoherence2 ); - hSpatParamRendCom->spreadCoherence2 = NULL; - } - } - - return; -} - - -/*------------------------------------------------------------------------- - * ivas_dirac_alloc_mem() - * - * Allocate stack memory for DirAC renderer - *------------------------------------------------------------------------*/ - -ivas_error ivas_dirac_alloc_mem( - DIRAC_REND_HANDLE hDirACRend, - const RENDERER_TYPE renderer_type, - const int16_t num_freq_bands, - DIRAC_DEC_STACK_MEM_HANDLE hDirAC_mem, - const int16_t hodirac_flag ) -{ - int16_t num_freq_bands_diff, size; - int16_t size_ho; - int16_t size_pf; - int16_t num_outputs_dir, num_outputs_diff; - int16_t num_protos_dir; - - num_protos_dir = hDirACRend->num_protos_dir; - - num_freq_bands_diff = hDirACRend->h_output_synthesis_psd_params.max_band_decorr; - - num_outputs_dir = hDirACRend->num_outputs_dir; - num_outputs_diff = hDirACRend->num_outputs_diff; - - size = num_freq_bands * num_outputs_dir; - if ( hodirac_flag ) - { - size_ho = size * DIRAC_HO_NUMSECTORS; - size_pf = num_freq_bands * DIRAC_HO_NUMSECTORS; - } - else - { - size_ho = size; - size_pf = num_freq_bands; - } - - /* PSD related buffers */ - hDirAC_mem->cy_auto_dir_smooth = NULL; - hDirAC_mem->proto_power_smooth = NULL; - hDirAC_mem->proto_power_diff_smooth = NULL; - hDirAC_mem->direct_responses_square = NULL; - hDirAC_mem->frame_dec_f = NULL; - if ( hDirACRend->synthesisConf != DIRAC_SYNTHESIS_GAIN_SHD ) - { - if ( ( hDirAC_mem->cy_auto_dir_smooth = (float *) malloc( sizeof( float ) * size ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); - } - set_zero( hDirAC_mem->cy_auto_dir_smooth, size ); - - if ( ( hDirAC_mem->proto_power_smooth = (float *) malloc( sizeof( float ) * size ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); - } - set_zero( hDirAC_mem->proto_power_smooth, size ); - - if ( ( hDirAC_mem->proto_power_diff_smooth = (float *) malloc( sizeof( float ) * size ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); - } - set_zero( hDirAC_mem->proto_power_diff_smooth, size ); - - if ( ( hDirAC_mem->direct_responses_square = (float *) malloc( sizeof( float ) * size ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); - } - set_zero( hDirAC_mem->direct_responses_square, size ); - if ( hDirACRend->proto_signal_decorr_on && ( renderer_type != RENDERER_BINAURAL_PARAMETRIC && renderer_type != RENDERER_BINAURAL_PARAMETRIC_ROOM && renderer_type != RENDERER_STEREO_PARAMETRIC ) ) - { - if ( ( hDirAC_mem->frame_dec_f = (float *) malloc( sizeof( float ) * 2 * num_outputs_diff * num_freq_bands ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); - } - } - } - hDirACRend->h_output_synthesis_psd_state.proto_power_smooth = hDirAC_mem->proto_power_smooth; - hDirACRend->h_output_synthesis_psd_state.proto_power_diff_smooth = hDirAC_mem->proto_power_diff_smooth; - hDirACRend->h_output_synthesis_psd_state.cy_auto_dir_smooth = hDirAC_mem->cy_auto_dir_smooth; - hDirACRend->h_output_synthesis_psd_state.direct_responses_square = hDirAC_mem->direct_responses_square; - - /* Target and smoothed nrg factors/gains */ - if ( ( hDirAC_mem->cy_cross_dir_smooth = (float *) malloc( sizeof( float ) * size_ho ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); - } - set_zero( hDirAC_mem->cy_cross_dir_smooth, size ); - - if ( hDirACRend->synthesisConf != DIRAC_SYNTHESIS_GAIN_SHD ) - { - if ( ( hDirAC_mem->cy_auto_diff_smooth = (float *) malloc( sizeof( float ) * size ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); - } - set_zero( hDirAC_mem->cy_auto_diff_smooth, size ); - } - else - { - if ( ( hDirAC_mem->cy_auto_diff_smooth = (float *) malloc( sizeof( float ) * num_outputs_diff * num_freq_bands_diff ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); - } - set_zero( hDirAC_mem->cy_auto_diff_smooth, num_outputs_diff * num_freq_bands_diff ); - } - hDirACRend->h_output_synthesis_psd_state.cy_cross_dir_smooth = hDirAC_mem->cy_cross_dir_smooth; - hDirACRend->h_output_synthesis_psd_state.cy_auto_diff_smooth = hDirAC_mem->cy_auto_diff_smooth; - - /*Responses (gains/factors)*/ - if ( ( hDirAC_mem->direct_responses = (float *) malloc( sizeof( float ) * size_ho ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); - } - set_zero( hDirAC_mem->direct_responses, size ); - - - hDirACRend->h_output_synthesis_psd_state.direct_responses = hDirAC_mem->direct_responses; - - /* Prototypes */ - hDirAC_mem->proto_direct_buffer_f = NULL; - hDirAC_mem->proto_diffuse_buffer_f = NULL; - if ( renderer_type != RENDERER_BINAURAL_PARAMETRIC && renderer_type != RENDERER_BINAURAL_PARAMETRIC_ROOM && renderer_type != RENDERER_STEREO_PARAMETRIC ) - { - if ( ( hDirAC_mem->proto_direct_buffer_f = (float *) malloc( sizeof( float ) * 2 * MAX_PARAM_SPATIAL_SUBFRAMES * num_protos_dir * num_freq_bands ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); - } - - if ( hDirACRend->proto_signal_decorr_on ) - { - if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_PSD_SHD ) - { - if ( ( hDirAC_mem->proto_diffuse_buffer_f = (float *) malloc( sizeof( float ) * 2 * MAX_PARAM_SPATIAL_SUBFRAMES * size ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); - } - } - else - { - if ( ( hDirAC_mem->proto_diffuse_buffer_f = (float *) malloc( sizeof( float ) * 2 * MAX_PARAM_SPATIAL_SUBFRAMES * num_outputs_diff * num_freq_bands ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); - } - } - } - } - hDirACRend->h_output_synthesis_psd_state.proto_direct_buffer_f = hDirAC_mem->proto_direct_buffer_f; - hDirACRend->h_output_synthesis_psd_state.proto_diffuse_buffer_f = hDirAC_mem->proto_diffuse_buffer_f; - - /* Gains/power factors*/ - hDirAC_mem->direct_power_factor = NULL; - hDirAC_mem->diffuse_power_factor = NULL; - - if ( renderer_type != RENDERER_BINAURAL_PARAMETRIC && renderer_type != RENDERER_BINAURAL_PARAMETRIC_ROOM && renderer_type != RENDERER_STEREO_PARAMETRIC ) - { - if ( ( hDirAC_mem->direct_power_factor = (float *) malloc( sizeof( float ) * size_pf ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); - } - if ( ( hDirAC_mem->diffuse_power_factor = (float *) malloc( sizeof( float ) * size_pf ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); - } - } - - hDirACRend->h_output_synthesis_psd_state.direct_power_factor = hDirAC_mem->direct_power_factor; - hDirACRend->h_output_synthesis_psd_state.diffuse_power_factor = hDirAC_mem->diffuse_power_factor; - - hDirAC_mem->reference_power = NULL; - hDirAC_mem->onset_filter = NULL; - if ( hDirACRend->synthesisConf != DIRAC_SYNTHESIS_GAIN_SHD ) - { - if ( renderer_type != RENDERER_BINAURAL_PARAMETRIC && renderer_type != RENDERER_BINAURAL_PARAMETRIC_ROOM && renderer_type != RENDERER_STEREO_PARAMETRIC ) - { - if ( ( hDirAC_mem->reference_power = (float *) malloc( sizeof( float ) * 2 * num_freq_bands ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); - } - if ( hDirACRend->proto_signal_decorr_on ) - { - if ( ( hDirAC_mem->onset_filter = (float *) malloc( sizeof( float ) * num_outputs_diff * num_freq_bands ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); - } - } - } - } - else - { - if ( num_protos_dir > 2 ) - { - if ( ( hDirAC_mem->reference_power = (float *) malloc( sizeof( float ) * 5 * num_freq_bands ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); - } - } - - if ( hDirACRend->proto_signal_decorr_on ) - { - if ( ( hDirAC_mem->onset_filter = (float *) malloc( sizeof( float ) * 2 * num_freq_bands ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); - } - } - } - - return IVAS_ERR_OK; -} - - -void ivas_dirac_free_mem( - DIRAC_DEC_STACK_MEM_HANDLE hDirAC_mem ) -{ - if ( hDirAC_mem->cy_auto_dir_smooth != NULL ) - { - free( hDirAC_mem->cy_auto_dir_smooth ); - } - if ( hDirAC_mem->proto_power_smooth != NULL ) - { - free( hDirAC_mem->proto_power_smooth ); - } - if ( hDirAC_mem->proto_power_diff_smooth != NULL ) - { - free( hDirAC_mem->proto_power_diff_smooth ); - } - if ( hDirAC_mem->direct_responses_square != NULL ) - { - free( hDirAC_mem->direct_responses_square ); - } - if ( hDirAC_mem->frame_dec_f != NULL ) - { - free( hDirAC_mem->frame_dec_f ); - } - if ( hDirAC_mem->cy_cross_dir_smooth != NULL ) - { - free( hDirAC_mem->cy_cross_dir_smooth ); - } - if ( hDirAC_mem->cy_auto_diff_smooth != NULL ) - { - free( hDirAC_mem->cy_auto_diff_smooth ); - } - if ( hDirAC_mem->direct_responses != NULL ) - { - free( hDirAC_mem->direct_responses ); - } - if ( hDirAC_mem->proto_direct_buffer_f != NULL ) - { - free( hDirAC_mem->proto_direct_buffer_f ); - } - if ( hDirAC_mem->proto_diffuse_buffer_f != NULL ) - { - free( hDirAC_mem->proto_diffuse_buffer_f ); - } - if ( hDirAC_mem->direct_power_factor != NULL ) - { - free( hDirAC_mem->direct_power_factor ); - } - if ( hDirAC_mem->diffuse_power_factor != NULL ) - { - free( hDirAC_mem->diffuse_power_factor ); - } - if ( hDirAC_mem->reference_power != NULL ) - { - free( hDirAC_mem->reference_power ); - } - if ( hDirAC_mem->onset_filter != NULL ) - { - free( hDirAC_mem->onset_filter ); - } - - return; -} - - -/*------------------------------------------------------------------------- - * compute_hoa_encoder_mtx() - * - * - *------------------------------------------------------------------------*/ - -void compute_hoa_encoder_mtx( - const float *azimuth, - const float *elevation, - float *response, - const int16_t num_responses, - const int16_t ambisonics_order ) -{ - int16_t k, num_sh; - - num_sh = ivas_sba_get_nchan( ambisonics_order, 0 ); - - for ( k = 0; k < num_responses; k++ ) - { - ivas_dirac_dec_get_response( (const int16_t) azimuth[k], (const int16_t) elevation[k], &response[k * num_sh], ambisonics_order ); - } - - return; -} - - -/*------------------------------------------------------------------------- - * ivas_dirac_dec_get_frequency_axis() - * - * DirAC decoding initialization - *------------------------------------------------------------------------*/ - -void ivas_dirac_dec_get_frequency_axis( - float *frequency_axis, - const int32_t output_Fs, - const int16_t num_freq_bands ) -{ - int16_t k; - float const_part; - - /* calc cldfb frequency axis */ - const_part = (float) output_Fs / ( 2.0f * (float) num_freq_bands ); - for ( k = 0; k < num_freq_bands; ++k ) - { - frequency_axis[k] = ( (float) k + 0.5f ) * const_part; - } - - return; -} - - -/*------------------------------------------------------------------------- - * Local functions - *-------------------------------------------------------------------------*/ - -void initDiffuseResponses( - float *diffuse_response_function, - const int16_t num_channels, - AUDIO_CONFIG output_config, - IVAS_OUTPUT_SETUP hOutSetup, - const int16_t ambisonics_order, - const IVAS_FORMAT ivas_format, - int16_t *num_ele_spk_no_diffuse_rendering, - AUDIO_CONFIG transport_config ) -{ - int16_t i, l, k, idx, num_horizontal_speakers; - *num_ele_spk_no_diffuse_rendering = 0; - - if ( output_config == AUDIO_CONFIG_MONO ) - { - diffuse_response_function[0] = 1.0f; - diffuse_response_function[1] = inv_sqrt( 3.0f ); - } - else if ( !( output_config == AUDIO_CONFIG_FOA || output_config == AUDIO_CONFIG_HOA2 || output_config == AUDIO_CONFIG_HOA3 ) ) - { - /* set diffuse response function */ - if ( ivas_format == MC_FORMAT && ( transport_config == AUDIO_CONFIG_5_1 || transport_config == AUDIO_CONFIG_7_1 ) && output_config == AUDIO_CONFIG_5_1_4 ) - { - num_horizontal_speakers = num_channels - NUM_ELEVATED_SPEAKERS; - - mvr2r( diffuse_response_CICP6, diffuse_response_function, num_horizontal_speakers ); - set_zero( &diffuse_response_function[num_horizontal_speakers], NUM_ELEVATED_SPEAKERS ); - *num_ele_spk_no_diffuse_rendering = NUM_ELEVATED_SPEAKERS; - } - else if ( ivas_format == MC_FORMAT && ( transport_config == AUDIO_CONFIG_5_1 || transport_config == AUDIO_CONFIG_7_1 ) && output_config == AUDIO_CONFIG_7_1_4 ) - { - num_horizontal_speakers = num_channels - NUM_ELEVATED_SPEAKERS; - - set_f( diffuse_response_function, sqrtf( 1.f / ( (float) num_horizontal_speakers ) ), num_horizontal_speakers ); - set_zero( &diffuse_response_function[num_horizontal_speakers], NUM_ELEVATED_SPEAKERS ); - *num_ele_spk_no_diffuse_rendering = NUM_ELEVATED_SPEAKERS; - } - else if ( ( ivas_format == MASA_FORMAT || ivas_format == MC_FORMAT ) && output_config == AUDIO_CONFIG_5_1 && num_channels == 5 ) - { - mvr2r( diffuse_response_CICP6, diffuse_response_function, num_channels ); - } - else if ( ( ivas_format == MASA_FORMAT || ivas_format == MC_FORMAT ) && output_config == AUDIO_CONFIG_5_1_2 && num_channels == 7 ) - { - mvr2r( diffuse_response_CICP14, diffuse_response_function, num_channels ); - } - else if ( ( ivas_format == MASA_FORMAT || ivas_format == MC_FORMAT ) && ( output_config == AUDIO_CONFIG_5_1_4 ) && ( num_channels == 9 ) ) - { - mvr2r( diffuse_response_CICP16, diffuse_response_function, num_channels ); - } - else if ( ( ivas_format == MASA_FORMAT || ivas_format == MC_FORMAT ) && ( output_config == AUDIO_CONFIG_LS_CUSTOM ) ) - { - if ( transport_config == AUDIO_CONFIG_5_1 || transport_config == AUDIO_CONFIG_7_1 ) - { - /* Detect loudspeakers with elevation */ - for ( i = 0, num_horizontal_speakers = 0; i < num_channels; i++ ) - { - if ( fabsf( hOutSetup.ls_elevation[i] ) <= 5.f ) - { - num_horizontal_speakers++; - diffuse_response_function[i] = 1.f; - } - else - { - *num_ele_spk_no_diffuse_rendering += 1; - diffuse_response_function[i] = 0.f; - } - } - /* Diffuse only to horizontal plane if enough loudspeakers */ - if ( num_horizontal_speakers > 2 ) - { - for ( i = 0; i < num_channels; i++ ) - { - diffuse_response_function[i] *= sqrtf( 1.f / (float) num_horizontal_speakers ); - } - } - else - { - *num_ele_spk_no_diffuse_rendering = 0; - set_f( diffuse_response_function, sqrtf( 1.f / (float) num_channels ), num_channels ); - } - } - else - { - set_f( diffuse_response_function, sqrtf( 1.f / (float) num_channels ), num_channels ); - } - } - else - { - set_f( diffuse_response_function, sqrtf( 1.f / (float) num_channels ), num_channels ); - } - } - else - { - idx = 0; - for ( l = 0; l <= ambisonics_order; l++ ) - { - for ( k = 0; k < ( 2 * l + 1 ); k++ ) - { - diffuse_response_function[idx++] = inv_sqrt( 2.0f * l + 1.0f ); - } - } - } - - return; -} - - -void protoSignalComputation_shd( - float RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], - float ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], - float *proto_direct_buffer_f, - float *proto_diffuse_buffer_f, - float *reference_power, - const int16_t slot_index, - const int16_t num_inputs, - const int16_t num_outputs_diff, - const int16_t num_freq_bands, - float *p_Rmat ) -{ - int16_t l, k; - float *p_proto_direct_buffer; - float *p_proto_diffuse_buffer; - int16_t Rmat_k[4]; - float W_real, W_imag; - float Y_real, Y_imag; - float *p_k[4]; - - k = 0; /* to avoid compilation warning */ - - p_proto_direct_buffer = proto_direct_buffer_f + slot_index * 2 * num_freq_bands * num_inputs; - p_proto_diffuse_buffer = proto_diffuse_buffer_f + slot_index * 2 * num_freq_bands * num_outputs_diff; - - if ( num_inputs == 1 ) - { - for ( l = 0; l < num_freq_bands; l++ ) - { - p_proto_direct_buffer[2 * l] = RealBuffer[0][0][l]; - p_proto_direct_buffer[2 * l + 1] = ImagBuffer[0][0][l]; - } - } - else if ( num_inputs == 2 ) - { - if ( p_Rmat != 0 ) - { - assert( num_inputs == 4 && "This code block should never be run with num_inputs != 4!" ); - - for ( l = 0; l < num_freq_bands; l++ ) - { - W_real = RealBuffer[0][0][l] + RealBuffer[1][0][l]; - W_imag = ImagBuffer[0][0][l] + ImagBuffer[1][0][l]; - - Y_real = RealBuffer[0][0][l] - RealBuffer[1][0][l]; - Y_imag = ImagBuffer[0][0][l] - ImagBuffer[1][0][l]; - - p_proto_direct_buffer[2 * l] = W_real; - p_proto_direct_buffer[2 * l + 1] = W_imag; - p_proto_direct_buffer[2 * num_freq_bands + 2 * l] = p_Rmat[0] * Y_real; - p_proto_direct_buffer[2 * num_freq_bands + 2 * l + 1] = p_Rmat[0] * Y_imag; - } - } - else - { - for ( l = 0; l < num_freq_bands; l++ ) - { - W_real = RealBuffer[0][0][l] + RealBuffer[1][0][l]; - W_imag = ImagBuffer[0][0][l] + ImagBuffer[1][0][l]; - - p_proto_direct_buffer[2 * l] = W_real; - p_proto_direct_buffer[2 * l + 1] = W_imag; - { - p_proto_direct_buffer[2 * num_freq_bands + 2 * l] = RealBuffer[0][0][l] - RealBuffer[1][0][l]; - p_proto_direct_buffer[2 * num_freq_bands + 2 * l + 1] = ImagBuffer[0][0][l] - ImagBuffer[1][0][l]; - } - } - } - } - else if ( num_inputs >= 4 ) - { - p_k[0] = p_proto_direct_buffer; - p_k[1] = p_proto_direct_buffer + 2 * num_freq_bands; - p_k[2] = p_proto_direct_buffer + 4 * num_freq_bands; - p_k[3] = p_proto_direct_buffer + 6 * num_freq_bands; - Rmat_k[0] = 0; - Rmat_k[1] = 1; - Rmat_k[2] = 2; - Rmat_k[3] = 0; - - if ( p_Rmat != 0 ) - { - assert( num_inputs == 4 && "This code block should never be run with num_inputs != 4!" ); - - for ( l = 0; l < num_freq_bands; l++ ) - { - *( p_k[0] ) = RealBuffer[0][0][l]; - reference_power[l + num_freq_bands] = *( p_k[0] ) * *( p_k[0] ); - p_k[0]++; - *( p_k[0] ) = ImagBuffer[0][0][l]; - reference_power[l + num_freq_bands] += *( p_k[0] ) * *( p_k[0] ); - p_k[0]++; - reference_power[l] = 0.5f * reference_power[l + num_freq_bands]; - - for ( k = 1; k < 4; k++ ) - { - *( p_k[k] ) = p_Rmat[3 * Rmat_k[k] + 1] * RealBuffer[1][0][l] + p_Rmat[3 * Rmat_k[k] + 2] * RealBuffer[2][0][l] + p_Rmat[3 * Rmat_k[k] + 0] * RealBuffer[3][0][l]; - reference_power[l + ( k + 1 ) * num_freq_bands] = *( p_k[k] ) * *( p_k[k] ); - p_k[k]++; - *( p_k[k] ) = p_Rmat[3 * Rmat_k[k] + 1] * ImagBuffer[1][0][l] + p_Rmat[3 * Rmat_k[k] + 2] * ImagBuffer[2][0][l] + p_Rmat[3 * Rmat_k[k] + 0] * ImagBuffer[3][0][l]; - reference_power[l + ( k + 1 ) * num_freq_bands] += *( p_k[k] ) * *( p_k[k] ); - p_k[k]++; - reference_power[l] += 0.5f * ( reference_power[l + ( k + 1 ) * num_freq_bands] ); - } - - for ( k = 1; k < 4; k++ ) - { - RealBuffer[k][0][l] = p_proto_direct_buffer[k * 2 * num_freq_bands + 2 * l]; - ImagBuffer[k][0][l] = p_proto_direct_buffer[k * 2 * num_freq_bands + 2 * l + 1]; - } - } - } - else - { - set_zero( reference_power, num_freq_bands ); - for ( k = 0; k < 4; k++ ) - { - for ( l = 0; l < num_freq_bands; l++ ) - { - p_proto_direct_buffer[k * 2 * num_freq_bands + 2 * l] = RealBuffer[k][0][l]; - p_proto_direct_buffer[k * 2 * num_freq_bands + 2 * l + 1] = ImagBuffer[k][0][l]; - reference_power[l + ( k + 1 ) * num_freq_bands] = RealBuffer[k][0][l] * RealBuffer[k][0][l] + ImagBuffer[k][0][l] * ImagBuffer[k][0][l]; - reference_power[l] += 0.5f * ( reference_power[l + ( k + 1 ) * num_freq_bands] ); - } - } - } - - /* Additional transport channels = planar SBA components of degree higher than 1*/ - for ( ; k < num_inputs; k++ ) - { - for ( l = 0; l < num_freq_bands; l++ ) - { - p_proto_direct_buffer[k * 2 * num_freq_bands + 2 * l] = RealBuffer[k][0][l]; - p_proto_direct_buffer[k * 2 * num_freq_bands + 2 * l + 1] = ImagBuffer[k][0][l]; - } - } - } - - - /*Copy direct to diffuse proto*/ - mvr2r( p_proto_direct_buffer, p_proto_diffuse_buffer, 2 * num_freq_bands * min( num_outputs_diff, num_inputs ) ); - - if ( num_inputs == 1 ) - { - /* Add comfort noise addition (CNA) to diffuse proto only*/ - for ( l = 0; l < num_freq_bands; l++ ) - { - p_proto_diffuse_buffer[2 * l] += RealBuffer[1][0][l]; - p_proto_diffuse_buffer[2 * l + 1] += ImagBuffer[1][0][l]; - } - } - - return; -} - - -void protoSignalComputation1( - float RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], - float ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], - float *proto_frame_f, - float *proto_direct_buffer_f, - float *reference_power, - float *proto_power_smooth, - const int16_t slot_index, - const int16_t num_outputs_diff, - const int16_t num_freq_bands ) -{ - int16_t l, k; - float *p_proto_buffer; - - p_proto_buffer = proto_direct_buffer_f + slot_index * 2 * num_freq_bands; - - for ( l = 0; l < num_freq_bands; l++ ) - { - reference_power[l] = RealBuffer[0][0][l] * RealBuffer[0][0][l] + ImagBuffer[0][0][l] * ImagBuffer[0][0][l]; - proto_power_smooth[l] += reference_power[l]; - p_proto_buffer[2 * l] = RealBuffer[0][0][l]; - p_proto_buffer[2 * l + 1] = ImagBuffer[0][0][l]; - - for ( k = 0; k < num_outputs_diff; k++ ) - { - proto_frame_f[2 * k * num_freq_bands + 2 * l] = RealBuffer[0][0][l]; - proto_frame_f[2 * k * num_freq_bands + 2 * l + 1] = ImagBuffer[0][0][l]; - } - } - - return; -} - - -void protoSignalComputation2( - float RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], - float ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], - float *proto_frame_f, - float *proto_direct_buffer_f, - float *reference_power, - float *proto_power_smooth, - const int16_t isloudspeaker, - const int16_t slot_index, - const int16_t num_freq_bands, - MASA_STEREO_TYPE_DETECT *stereo_type_detect ) -{ - int16_t l; - float *p_proto_buffer; - float Real_aux, Imag_aux; - - float left_bb_power, right_bb_power, total_bb_power, lr_bb_power; - float lr_total_bb_ratio; - float a, b; - - float left_hi_power, right_hi_power, total_hi_power, lr_hi_power; - float lr_total_hi_ratio; - float a2, b2; - - float sum_power; - float sum_total_ratio[MASA_SUM_FREQ_RANGE_BINS]; - float min_sum_total_ratio; - float min_sum_total_ratio_db; - - float RealSubtract, ImagSubtract; - - float interpolatorSpaced = 0.0f; - float interpolatorDmx = 1.0f; - - int16_t dipole_freq_range[2]; - float tempSpaced, tempDmx; - - if ( isloudspeaker ) - { - p_proto_buffer = proto_direct_buffer_f + slot_index * 2 * num_freq_bands * 3; - - for ( l = 0; l < num_freq_bands; l++ ) - { - float Left_power; - float Right_power; - Real_aux = RealBuffer[0][0][l] + RealBuffer[1][0][l]; - Imag_aux = ImagBuffer[0][0][l] + ImagBuffer[1][0][l]; - - Left_power = RealBuffer[0][0][l] * RealBuffer[0][0][l] + ImagBuffer[0][0][l] * ImagBuffer[0][0][l]; - Right_power = RealBuffer[1][0][l] * RealBuffer[1][0][l] + ImagBuffer[1][0][l] * ImagBuffer[1][0][l]; - - reference_power[l] = Left_power + Right_power; - proto_power_smooth[l] += Real_aux * Real_aux + Imag_aux * Imag_aux; - - p_proto_buffer[2 * l] = Real_aux; - p_proto_buffer[2 * l + 1] = Imag_aux; - proto_power_smooth[l + num_freq_bands] += RealBuffer[0][0][l] * RealBuffer[0][0][l] + ImagBuffer[0][0][l] * ImagBuffer[0][0][l]; - p_proto_buffer[2 * num_freq_bands + 2 * l] = RealBuffer[0][0][l]; - p_proto_buffer[2 * num_freq_bands + 2 * l + 1] = ImagBuffer[0][0][l]; - - proto_power_smooth[l + 2 * num_freq_bands] += RealBuffer[1][0][l] * RealBuffer[1][0][l]; - proto_power_smooth[l + 2 * num_freq_bands] += ImagBuffer[1][0][l] * ImagBuffer[1][0][l]; - p_proto_buffer[4 * num_freq_bands + 2 * l] = RealBuffer[1][0][l]; - p_proto_buffer[4 * num_freq_bands + 2 * l + 1] = ImagBuffer[1][0][l]; - - proto_frame_f[2 * l] = Real_aux; - proto_frame_f[2 * l + 1] = Imag_aux; - - proto_frame_f[2 * num_freq_bands + 2 * l] = RealBuffer[0][0][l]; - proto_frame_f[2 * num_freq_bands + 2 * l + 1] = ImagBuffer[0][0][l]; - proto_frame_f[4 * num_freq_bands + 2 * l] = RealBuffer[1][0][l]; - proto_frame_f[4 * num_freq_bands + 2 * l + 1] = ImagBuffer[1][0][l]; - } - } - else if ( stereo_type_detect != NULL ) - { - p_proto_buffer = proto_direct_buffer_f + slot_index * 2 * num_freq_bands * 2; - - left_bb_power = 0.0f; - right_bb_power = 0.0f; - total_bb_power = 0.0f; - - left_hi_power = 0.0f; - right_hi_power = 0.0f; - total_hi_power = 0.0f; - - dipole_freq_range[0] = stereo_type_detect->dipole_freq_range[0]; - dipole_freq_range[1] = stereo_type_detect->dipole_freq_range[1]; - - a = 0.01f; /* Temporal smoothing coefficient */ - b = 1.0f - a; /* Temporal smoothing coefficient */ - a2 = 0.1f; /* Temporal smoothing coefficient */ - b2 = 1.0f - a2; /* Temporal smoothing coefficient */ - - if ( stereo_type_detect->interpolator > 0 ) - { - if ( stereo_type_detect->type_change_direction == MASA_STEREO_SPACED_MICS ) - { - interpolatorSpaced = ( (float) ( stereo_type_detect->interpolator ) ) / ( (float) MASA_STEREO_INTERPOLATION_SLOTS ); - interpolatorDmx = 1.0f - interpolatorSpaced; - } - else - { - interpolatorDmx = ( (float) ( stereo_type_detect->interpolator ) ) / ( (float) MASA_STEREO_INTERPOLATION_SLOTS ); - interpolatorSpaced = 1.0f - interpolatorDmx; - } - } - - for ( l = 0; l < num_freq_bands; l++ ) - { - float Left_power; - float Right_power; - - /* Compute sum signal */ - Real_aux = RealBuffer[0][0][l] + RealBuffer[1][0][l]; - Imag_aux = ImagBuffer[0][0][l] + ImagBuffer[1][0][l]; - - /* Compute reference power */ - Left_power = RealBuffer[0][0][l] * RealBuffer[0][0][l] + ImagBuffer[0][0][l] * ImagBuffer[0][0][l]; - Right_power = RealBuffer[1][0][l] * RealBuffer[1][0][l] + ImagBuffer[1][0][l] * ImagBuffer[1][0][l]; - - reference_power[l] = Left_power + Right_power; - - left_bb_power += Left_power; - right_bb_power += Right_power; - total_bb_power += reference_power[l]; - - if ( l > MASA_HI_FREQ_START_BIN ) - { - left_hi_power += Left_power; - right_hi_power += Right_power; - total_hi_power += reference_power[l]; - } - - if ( l < min( num_freq_bands, MASA_SUM_FREQ_RANGE_BINS ) ) - { - sum_power = Real_aux * Real_aux + Imag_aux * Imag_aux; - - stereo_type_detect->sum_power[l] = a * sum_power + b * stereo_type_detect->sum_power[l]; - stereo_type_detect->total_power[l] = a * reference_power[l] + b * stereo_type_detect->total_power[l]; - - sum_total_ratio[l] = stereo_type_detect->sum_power[l] / ( stereo_type_detect->total_power[l] + EPSILON ); - } - - if ( l == 0 ) - { - RealSubtract = RealBuffer[0][0][l] - RealBuffer[1][0][l]; - ImagSubtract = ImagBuffer[0][0][l] - ImagBuffer[1][0][l]; - stereo_type_detect->subtract_power_y += RealSubtract * RealSubtract + ImagSubtract * ImagSubtract; - } - - /* Compute protos (and their power) for direct sound rendering */ - - /* W prototype */ - if ( stereo_type_detect->interpolator > 0 ) - { - if ( l < ( dipole_freq_range[1] - 1 ) || l >= MASA_SUM_PROTO_START_BIN ) - { - Real_aux = interpolatorSpaced * 0.5f * Real_aux + interpolatorDmx * Real_aux; - Imag_aux = interpolatorSpaced * 0.5f * Imag_aux + interpolatorDmx * Imag_aux; - proto_power_smooth[l] += Real_aux * Real_aux + Imag_aux * Imag_aux; - p_proto_buffer[2 * l] = Real_aux; - p_proto_buffer[2 * l + 1] = Imag_aux; - } - else - { - tempSpaced = RealBuffer[0][0][l] * RealBuffer[0][0][l] + ImagBuffer[0][0][l] * ImagBuffer[0][0][l]; - tempDmx = Real_aux * Real_aux + Imag_aux * Imag_aux; - proto_power_smooth[l] += interpolatorSpaced * tempSpaced + interpolatorDmx * tempDmx; - p_proto_buffer[2 * l] = interpolatorSpaced * RealBuffer[0][0][l] + interpolatorDmx * Real_aux; - p_proto_buffer[2 * l + 1] = interpolatorSpaced * ImagBuffer[0][0][l] + interpolatorDmx * Imag_aux; - } - } - else if ( stereo_type_detect->masa_stereo_type == MASA_STEREO_SPACED_MICS ) - { - if ( l < ( dipole_freq_range[1] - 1 ) || l >= MASA_SUM_PROTO_START_BIN ) - { - Real_aux *= 0.5f; - Imag_aux *= 0.5f; - proto_power_smooth[l] += Real_aux * Real_aux + Imag_aux * Imag_aux; - p_proto_buffer[2 * l] = Real_aux; - p_proto_buffer[2 * l + 1] = Imag_aux; - } - else - { - proto_power_smooth[l] += RealBuffer[0][0][l] * RealBuffer[0][0][l] + ImagBuffer[0][0][l] * ImagBuffer[0][0][l]; - p_proto_buffer[2 * l] = RealBuffer[0][0][l]; - p_proto_buffer[2 * l + 1] = ImagBuffer[0][0][l]; - } - } - else - { - proto_power_smooth[l] += Real_aux * Real_aux + Imag_aux * Imag_aux; - p_proto_buffer[2 * l] = Real_aux; - p_proto_buffer[2 * l + 1] = Imag_aux; - } - - /* Y prototype */ - if ( stereo_type_detect->interpolator > 0 ) - { - if ( l < ( dipole_freq_range[0] ) ) - { - p_proto_buffer[2 * num_freq_bands + 2 * l] = interpolatorSpaced * p_proto_buffer[2 * l] + interpolatorDmx * ( RealBuffer[0][0][l] - RealBuffer[1][0][l] ); - p_proto_buffer[2 * num_freq_bands + 2 * l + 1] = interpolatorSpaced * p_proto_buffer[2 * l + 1] + interpolatorDmx * ( ImagBuffer[0][0][l] - ImagBuffer[1][0][l] ); - } - else if ( l < ( dipole_freq_range[1] ) ) - { - p_proto_buffer[2 * num_freq_bands + 2 * l] = interpolatorSpaced * ( ImagBuffer[0][0][l] - ImagBuffer[1][0][l] ) + interpolatorDmx * ( RealBuffer[0][0][l] - RealBuffer[1][0][l] ); - p_proto_buffer[2 * num_freq_bands + 2 * l + 1] = interpolatorSpaced * ( -( RealBuffer[0][0][l] - RealBuffer[1][0][l] ) ) + interpolatorDmx * ( ImagBuffer[0][0][l] - ImagBuffer[1][0][l] ); - } - else - { - p_proto_buffer[2 * num_freq_bands + 2 * l] = interpolatorSpaced * p_proto_buffer[2 * l] + interpolatorDmx * ( RealBuffer[0][0][l] - RealBuffer[1][0][l] ); - p_proto_buffer[2 * num_freq_bands + 2 * l + 1] = interpolatorSpaced * p_proto_buffer[2 * l + 1] + interpolatorDmx * ( ImagBuffer[0][0][l] - ImagBuffer[1][0][l] ); - } - proto_power_smooth[l + num_freq_bands] += p_proto_buffer[2 * num_freq_bands + 2 * l] * p_proto_buffer[2 * num_freq_bands + 2 * l] + p_proto_buffer[2 * num_freq_bands + 2 * l + 1] * p_proto_buffer[2 * num_freq_bands + 2 * l + 1]; - } - else if ( stereo_type_detect->masa_stereo_type == MASA_STEREO_SPACED_MICS ) - { - if ( l < ( dipole_freq_range[0] ) ) /* proto = W */ - { - p_proto_buffer[2 * num_freq_bands + 2 * l] = p_proto_buffer[2 * l]; - p_proto_buffer[2 * num_freq_bands + 2 * l + 1] = p_proto_buffer[2 * l + 1]; - proto_power_smooth[l + num_freq_bands] = proto_power_smooth[l]; - } - else if ( l < ( dipole_freq_range[1] ) ) /* proto = -i * (x1-x2) * eq */ - { - p_proto_buffer[2 * num_freq_bands + 2 * l] = ( ImagBuffer[0][0][l] - ImagBuffer[1][0][l] ); - p_proto_buffer[2 * num_freq_bands + 2 * l + 1] = -( RealBuffer[0][0][l] - RealBuffer[1][0][l] ); - proto_power_smooth[l + num_freq_bands] += p_proto_buffer[2 * num_freq_bands + 2 * l] * p_proto_buffer[2 * num_freq_bands + 2 * l] + p_proto_buffer[2 * num_freq_bands + 2 * l + 1] * p_proto_buffer[2 * num_freq_bands + 2 * l + 1]; - } - else /* proto = W */ - { - p_proto_buffer[2 * num_freq_bands + 2 * l] = p_proto_buffer[2 * l]; - p_proto_buffer[2 * num_freq_bands + 2 * l + 1] = p_proto_buffer[2 * l + 1]; - proto_power_smooth[l + num_freq_bands] = proto_power_smooth[l]; - } - } - else - { - p_proto_buffer[2 * num_freq_bands + 2 * l] = RealBuffer[0][0][l] - RealBuffer[1][0][l]; - p_proto_buffer[2 * num_freq_bands + 2 * l + 1] = ImagBuffer[0][0][l] - ImagBuffer[1][0][l]; - proto_power_smooth[l + num_freq_bands] += p_proto_buffer[2 * num_freq_bands + 2 * l] * p_proto_buffer[2 * num_freq_bands + 2 * l] + p_proto_buffer[2 * num_freq_bands + 2 * l + 1] * p_proto_buffer[2 * num_freq_bands + 2 * l + 1]; - } - - /* Compute protos for decorrelation */ - proto_frame_f[2 * l] = Real_aux; - proto_frame_f[2 * l + 1] = Imag_aux; - proto_frame_f[2 * num_freq_bands + 2 * l] = RealBuffer[0][0][l]; - proto_frame_f[2 * num_freq_bands + 2 * l + 1] = ImagBuffer[0][0][l]; - proto_frame_f[4 * num_freq_bands + 2 * l] = RealBuffer[1][0][l]; - proto_frame_f[4 * num_freq_bands + 2 * l + 1] = ImagBuffer[1][0][l]; - } - - if ( stereo_type_detect->interpolator > 0 ) - { - stereo_type_detect->interpolator++; - if ( stereo_type_detect->interpolator == MASA_STEREO_INTERPOLATION_SLOTS ) - { - stereo_type_detect->interpolator = 0; - stereo_type_detect->current_stereo_type = stereo_type_detect->type_change_direction; - } - } - - stereo_type_detect->left_bb_power = a * left_bb_power + b * stereo_type_detect->left_bb_power; - stereo_type_detect->right_bb_power = a * right_bb_power + b * stereo_type_detect->right_bb_power; - stereo_type_detect->total_bb_power = a * total_bb_power + b * stereo_type_detect->total_bb_power; - - lr_bb_power = ( stereo_type_detect->left_bb_power < stereo_type_detect->right_bb_power ) ? stereo_type_detect->left_bb_power : stereo_type_detect->right_bb_power; - lr_bb_power *= 2.0f; - lr_total_bb_ratio = 10.0f * log10f( lr_bb_power / ( stereo_type_detect->total_bb_power + EPSILON ) ); - - stereo_type_detect->left_hi_power = a2 * left_hi_power + b2 * stereo_type_detect->left_hi_power; - stereo_type_detect->right_hi_power = a2 * right_hi_power + b2 * stereo_type_detect->right_hi_power; - stereo_type_detect->total_hi_power = a2 * total_hi_power + b2 * stereo_type_detect->total_hi_power; - - lr_hi_power = ( stereo_type_detect->left_hi_power < stereo_type_detect->right_hi_power ) ? stereo_type_detect->left_hi_power : stereo_type_detect->right_hi_power; - lr_hi_power *= 2.0f; - lr_total_hi_ratio = 10.0f * log10f( lr_hi_power / ( stereo_type_detect->total_hi_power + EPSILON ) ); - - minimum( sum_total_ratio, min( num_freq_bands, MASA_SUM_FREQ_RANGE_BINS ), &min_sum_total_ratio ); - min_sum_total_ratio_db = 10.0f * log10f( min_sum_total_ratio ); - - stereo_type_detect->lr_total_bb_ratio_db = lr_total_bb_ratio; - stereo_type_detect->lr_total_hi_ratio_db = lr_total_hi_ratio; - stereo_type_detect->min_sum_total_ratio_db = min_sum_total_ratio_db; - - ivas_masa_stereotype_detection( stereo_type_detect ); - } - else - { - p_proto_buffer = proto_direct_buffer_f + slot_index * 2 * num_freq_bands * 2; - - for ( l = 0; l < num_freq_bands; l++ ) - { - Real_aux = RealBuffer[0][0][l] + RealBuffer[1][0][l]; - Imag_aux = ImagBuffer[0][0][l] + ImagBuffer[1][0][l]; - - reference_power[l] = Real_aux * Real_aux + Imag_aux * Imag_aux; - proto_power_smooth[l] += reference_power[l]; - p_proto_buffer[2 * l] = Real_aux; - p_proto_buffer[2 * l + 1] = Imag_aux; - - p_proto_buffer[2 * num_freq_bands + 2 * l] = RealBuffer[0][0][l] - RealBuffer[1][0][l]; - p_proto_buffer[2 * num_freq_bands + 2 * l + 1] = ImagBuffer[0][0][l] - ImagBuffer[1][0][l]; - proto_power_smooth[l + num_freq_bands] += p_proto_buffer[2 * num_freq_bands + 2 * l] * p_proto_buffer[2 * num_freq_bands + 2 * l] + p_proto_buffer[2 * num_freq_bands + 2 * l + 1] * p_proto_buffer[2 * num_freq_bands + 2 * l + 1]; - - proto_frame_f[2 * l] = Real_aux; - proto_frame_f[2 * l + 1] = Imag_aux; - - proto_frame_f[2 * num_freq_bands + 2 * l] = RealBuffer[0][0][l]; - proto_frame_f[2 * num_freq_bands + 2 * l + 1] = ImagBuffer[0][0][l]; - proto_frame_f[4 * num_freq_bands + 2 * l] = RealBuffer[1][0][l]; - proto_frame_f[4 * num_freq_bands + 2 * l + 1] = ImagBuffer[1][0][l]; - } - } - - return; -} - - -void protoSignalComputation4( - float RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], - float ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], - float *proto_frame_f, - float *proto_direct_buffer_f, - float *reference_power, - float *proto_power_smooth, - const int16_t slot_index, - const int16_t num_outputs_diff, - const int16_t num_freq_bands, - const float *mtx_hoa_decoder, - const int16_t nchan_transport, - const int16_t *sba_map_tc_ind ) -{ - int16_t k, l; - int16_t n; - float sq_tmp; - float *p_proto_buffer; - - set_zero( reference_power, num_freq_bands ); - for ( k = 0; k < 4; k++ ) - { - for ( l = 0; l < num_freq_bands; l++ ) - { - sq_tmp = RealBuffer[k][0][l] * RealBuffer[k][0][l] + ImagBuffer[k][0][l] * ImagBuffer[k][0][l]; - reference_power[l] += 0.5f * sq_tmp; - } - } - - /*For decorrelated diffuseness*/ - for ( l = 0; l < num_outputs_diff; l++ ) - { - for ( k = 0; k < num_freq_bands; k++ ) - { - proto_frame_f[2 * l * num_freq_bands + 2 * k] = 0.f; - proto_frame_f[2 * l * num_freq_bands + 2 * k + 1] = 0.f; - for ( n = 0; n < nchan_transport; n++ ) - { - proto_frame_f[2 * l * num_freq_bands + 2 * k] += RealBuffer[n][0][k] * mtx_hoa_decoder[l * 16 + sba_map_tc_ind[n]]; - proto_frame_f[2 * l * num_freq_bands + 2 * k + 1] += ImagBuffer[n][0][k] * mtx_hoa_decoder[l * 16 + sba_map_tc_ind[n]]; - } - } - } - - p_proto_buffer = proto_direct_buffer_f + slot_index * 2 * num_freq_bands * num_outputs_diff; - for ( k = 0; k < num_outputs_diff; k++ ) - { - for ( l = 0; l < num_freq_bands; l++ ) - { - sq_tmp = proto_frame_f[k * 2 * num_freq_bands + 2 * l] * proto_frame_f[k * 2 * num_freq_bands + 2 * l] + proto_frame_f[k * 2 * num_freq_bands + 2 * l + 1] * proto_frame_f[k * 2 * num_freq_bands + 2 * l + 1]; - proto_power_smooth[l + k * num_freq_bands] += sq_tmp; - p_proto_buffer[k * 2 * num_freq_bands + 2 * l] = proto_frame_f[k * 2 * num_freq_bands + 2 * l]; - p_proto_buffer[k * 2 * num_freq_bands + 2 * l + 1] = proto_frame_f[k * 2 * num_freq_bands + 2 * l + 1]; - } - } - - return; -} - - -/*------------------------------------------------------------------------- - * ivas_dirac_dec_compute_diffuse_proto() - * - * Compute diffuse prototype buffer and smooth power, only for decorrelated bands - *------------------------------------------------------------------------*/ - -void ivas_dirac_dec_compute_diffuse_proto( - DIRAC_REND_HANDLE hDirACRend, - const int16_t num_freq_bands, - const int16_t slot_idx /* i : slot index */ -) -{ - int16_t k, l; - int16_t num_freq_bands_diff; - float *p_diff_buffer, *p_diff_buffer_1; - float *p_proto_diff, *p_power_smooth, *proto_frame_dec_f; - DIRAC_OUTPUT_SYNTHESIS_PARAMS *h_dirac_output_synthesis_params; - DIRAC_OUTPUT_SYNTHESIS_STATE *h_dirac_output_synthesis_state; - int16_t m; - float *p_hoa_enc; - - proto_frame_dec_f = hDirACRend->proto_frame_dec_f; - h_dirac_output_synthesis_params = &( hDirACRend->h_output_synthesis_psd_params ); - h_dirac_output_synthesis_state = &( hDirACRend->h_output_synthesis_psd_state ); - - num_freq_bands_diff = h_dirac_output_synthesis_params->max_band_decorr; - - p_diff_buffer = h_dirac_output_synthesis_state->proto_diffuse_buffer_f + slot_idx * 2 * num_freq_bands_diff * hDirACRend->hOutSetup.nchan_out_woLFE; - p_diff_buffer_1 = p_diff_buffer + 1; - p_power_smooth = h_dirac_output_synthesis_state->proto_power_diff_smooth; - - if ( hDirACRend->synthesisConf != DIRAC_SYNTHESIS_PSD_SHD ) - { - for ( k = 0; k < hDirACRend->hOutSetup.nchan_out_woLFE; k++ ) - { - p_proto_diff = proto_frame_dec_f + k * 2 * num_freq_bands; - for ( l = 0; l < num_freq_bands_diff; l++ ) - { - *p_diff_buffer = *( p_proto_diff++ ); - *p_diff_buffer_1 = *( p_proto_diff++ ); - *( p_power_smooth++ ) += ( *p_diff_buffer ) * ( *p_diff_buffer ) + ( *p_diff_buffer_1 ) * ( *p_diff_buffer_1 ); - p_diff_buffer += 2; - p_diff_buffer_1 += 2; - } - } - } - else - { - /*DIRAC_SYNTHESIS_PSD_SHD: Virtual LS->HOA encoding*/ - for ( k = 0; k < hDirACRend->hOutSetup.nchan_out_woLFE; k++ ) - { - for ( l = 0; l < num_freq_bands_diff; l++ ) - { - p_hoa_enc = hDirACRend->hoa_encoder + k; - p_proto_diff = proto_frame_dec_f + 2 * l; - - *p_diff_buffer = 0.f; - *p_diff_buffer_1 = 0.f; - - /*LS to HOA*/ - for ( m = 0; m < hDirACRend->num_outputs_diff; m++ ) - { - *p_diff_buffer += ( *p_hoa_enc ) * ( *p_proto_diff ); - *p_diff_buffer_1 += ( *p_hoa_enc ) * ( *( p_proto_diff + 1 ) ); - p_hoa_enc += hDirACRend->hOutSetup.nchan_out_woLFE; - p_proto_diff += 2 * num_freq_bands; - } - - *( p_power_smooth++ ) += ( *p_diff_buffer ) * ( *p_diff_buffer ) + ( *p_diff_buffer_1 ) * ( *p_diff_buffer_1 ); - p_diff_buffer += 2; - p_diff_buffer_1 += 2; - } - } - } - - return; -} - - -/*------------------------------------------------------------------------- - * computeDirectionAngles() - * - *------------------------------------------------------------------------*/ - -void computeDirectionAngles( - float *intensity_real_x, - float *intensity_real_y, - float *intensity_real_z, - const int16_t num_frequency_bands, - int16_t *azimuth, - int16_t *elevation ) -{ - int16_t k; - float intensityNorm; - float x, y, z, radius; - - for ( k = 0; k < num_frequency_bands; ++k ) - - { - intensityNorm = *( intensity_real_x ) * *( intensity_real_x ) + - *( intensity_real_y ) * *( intensity_real_y ) + - *( intensity_real_z ) * *( intensity_real_z ); - - if ( intensityNorm <= EPSILON ) - { - intensityNorm = 1.0f; - x = 1.0f; - y = 0.0f; - z = 0.0f; - intensity_real_x++; - intensity_real_y++; - intensity_real_z++; - } - else - { - intensityNorm = sqrtf( 1.f / intensityNorm ); - x = *( intensity_real_x++ ) * intensityNorm; - y = *( intensity_real_y++ ) * intensityNorm; - z = *( intensity_real_z++ ) * intensityNorm; - } - radius = sqrtf( x * x + y * y ); - azimuth[k] = (int16_t) ( max( -180.0f, min( 180.0f, atan2f( y, x ) / EVS_PI * 180.0f ) ) + 0.5f ); - elevation[k] = (int16_t) ( max( -90.0f, min( 180.0f, atan2f( z, radius ) / EVS_PI * 180.0f ) ) + 0.5f ); - } - - return; -} - - -/*------------------------------------------------------------------------- - * ivas_masa_init_stereotype_detection() - * - * Initialize stereo transport signal type detection - *------------------------------------------------------------------------*/ - -void ivas_masa_init_stereotype_detection( - MASA_STEREO_TYPE_DETECT *stereo_type_detect ) -{ - stereo_type_detect->masa_stereo_type = MASA_STEREO_DOWNMIX; - stereo_type_detect->current_stereo_type = MASA_STEREO_DOWNMIX; - stereo_type_detect->type_change_direction = MASA_STEREO_DOWNMIX; - - stereo_type_detect->counter = 0; - stereo_type_detect->interpolator = 0; - - stereo_type_detect->dipole_freq_range[0] = 1; - stereo_type_detect->dipole_freq_range[1] = 3; - - stereo_type_detect->left_bb_power = 0.0f; /* Broadband estimates */ - stereo_type_detect->right_bb_power = 0.0f; - stereo_type_detect->total_bb_power = 0.0f; - - stereo_type_detect->left_hi_power = 0.0f; /* High-frequency estimates */ - stereo_type_detect->right_hi_power = 0.0f; - stereo_type_detect->total_hi_power = 0.0f; - - set_zero( stereo_type_detect->sum_power, MASA_SUM_FREQ_RANGE_BINS ); - set_zero( stereo_type_detect->total_power, MASA_SUM_FREQ_RANGE_BINS ); - - stereo_type_detect->subtract_power_y = 0.0f; - stereo_type_detect->subtract_power_y_smooth = 0.0f; - stereo_type_detect->target_power_y_smooth = 0.0f; - - stereo_type_detect->lr_total_bb_ratio_db = 0.0f; - stereo_type_detect->lr_total_hi_ratio_db = 0.0f; - stereo_type_detect->min_sum_total_ratio_db = 0.0f; - stereo_type_detect->subtract_target_ratio_db = 0.0f; - - return; -} - - -/*------------------------------------------------------------------------- - * ivas_masa_stereotype_detection() - * - * Detect the type of the transport audio signals - *------------------------------------------------------------------------*/ - -void ivas_masa_stereotype_detection( - MASA_STEREO_TYPE_DETECT *stereo_type_detect ) -{ - float lr_total_bb_ratio_db = stereo_type_detect->lr_total_bb_ratio_db; - float lr_total_hi_ratio_db = stereo_type_detect->lr_total_hi_ratio_db; - float min_sum_total_ratio_db = stereo_type_detect->min_sum_total_ratio_db; - float subtract_target_ratio_db = stereo_type_detect->subtract_target_ratio_db; - float change_to_spaced; - int16_t change_to_spaced_selection; - float change_to_downmix; - float change_to_downmix2; - int16_t change_to_downmix_selection; - float subtract_temp; - float min_sum_temp; - float lr_total_bb_temp; - float lr_total_hi_temp; - - /* Determine if the determined features match the spaced mic type */ - change_to_spaced_selection = 0; - if ( subtract_target_ratio_db < -3.0f ) - { - subtract_temp = ( -subtract_target_ratio_db - 3.0f ) / 3.0f; - min_sum_temp = max( -min_sum_total_ratio_db / 6.0f, 0.0f ); - lr_total_bb_temp = lr_total_bb_ratio_db / 6.0f; - - change_to_spaced = subtract_temp + min_sum_temp + lr_total_bb_temp; - - if ( change_to_spaced >= 1.0f ) - { - change_to_spaced_selection = 1; - } - } - - /* Determine if the determined features match the downmix type, according to a metric */ - change_to_downmix_selection = 0; - if ( subtract_target_ratio_db > 0.0f ) - { - subtract_temp = subtract_target_ratio_db / 3.0f; - min_sum_temp = ( min_sum_total_ratio_db + 1.0f ) / 6.0f; - lr_total_bb_temp = -lr_total_bb_ratio_db / 6.0f; - - change_to_downmix = subtract_temp + min_sum_temp + lr_total_bb_temp; - - if ( change_to_downmix >= 1.0f ) - { - change_to_downmix_selection = 1; - } - } - - /* Determine if the determined features match the downmix type, according to another metric */ - if ( lr_total_hi_ratio_db < -12.0f ) - { - subtract_temp = ( subtract_target_ratio_db + 4.0f ) / 3.0f; - min_sum_temp = min_sum_total_ratio_db / 6.0f; - lr_total_hi_temp = ( -lr_total_hi_ratio_db - 12.0f ) / 3.0f; - - change_to_downmix2 = subtract_temp + min_sum_temp + lr_total_hi_temp; - - if ( change_to_downmix2 >= 1.0f ) - { - change_to_downmix_selection = 1; - } - } - - if ( stereo_type_detect->counter < 400 ) - { - stereo_type_detect->counter++; - } - else - { - if ( change_to_spaced_selection == 1 ) - { - stereo_type_detect->masa_stereo_type = MASA_STEREO_SPACED_MICS; - } - else if ( change_to_downmix_selection == 1 ) - { - stereo_type_detect->masa_stereo_type = MASA_STEREO_DOWNMIX; - } - } - - if ( stereo_type_detect->interpolator == 0 ) - { - if ( stereo_type_detect->current_stereo_type != stereo_type_detect->masa_stereo_type ) - { - stereo_type_detect->interpolator = 1; - stereo_type_detect->type_change_direction = stereo_type_detect->masa_stereo_type; - } - } - - return; -} - - -/*------------------------------------------------------------------------- - * computeIntensityVector_dec() - * - * - *------------------------------------------------------------------------*/ - -void computeIntensityVector_dec( - float Cldfb_RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], - float Cldfb_ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], - const int16_t num_frequency_bands, - float *intensity_real_x, - float *intensity_real_y, - float *intensity_real_z ) -{ - /* - * W = a + ib; Y = c + id - * real(W*Y') = ac + bd - */ - int16_t i; - float real, img; - - for ( i = 0; i < num_frequency_bands; ++i ) - { - real = Cldfb_RealBuffer[0][0][i]; - img = Cldfb_ImagBuffer[0][0][i]; - intensity_real_x[i] = Cldfb_RealBuffer[3][0][i] * real + Cldfb_ImagBuffer[3][0][i] * img; - intensity_real_y[i] = Cldfb_RealBuffer[1][0][i] * real + Cldfb_ImagBuffer[1][0][i] * img; - intensity_real_z[i] = Cldfb_RealBuffer[2][0][i] * real + Cldfb_ImagBuffer[2][0][i] * img; - } - - return; -} - - -/*------------------------------------------------------------------------- - * ivas_lfe_synth_with_cldfb() - * - * - *------------------------------------------------------------------------*/ - -void ivas_lfe_synth_with_cldfb( - MCMASA_LFE_SYNTH_DATA_HANDLE hMasaLfeSynth, - float RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], - float ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], - float RealBufferLfe[MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], - float ImagBufferLfe[MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], - const int16_t slot_index, - const int16_t subframe_index, - const int16_t nchan_transport ) -{ - float lfeGain; - float transportGain; - float protoLfeReal, protoLfeImag; - int16_t i; - float transportEne, protoLfeEne, targetEneLfe, targetEneTrans; - - set_zero( RealBufferLfe[slot_index], CLDFB_NO_CHANNELS_MAX ); - set_zero( ImagBufferLfe[slot_index], CLDFB_NO_CHANNELS_MAX ); - - protoLfeReal = RealBuffer[0][0][0]; - protoLfeImag = ImagBuffer[0][0][0]; - transportEne = RealBuffer[0][0][0] * RealBuffer[0][0][0] + ImagBuffer[0][0][0] * ImagBuffer[0][0][0]; - for ( i = 1; i < nchan_transport; i++ ) - { - protoLfeReal += RealBuffer[i][0][0]; - protoLfeImag += ImagBuffer[i][0][0]; - transportEne += RealBuffer[i][0][0] * RealBuffer[i][0][0] + ImagBuffer[i][0][0] * ImagBuffer[i][0][0]; - } - protoLfeEne = protoLfeReal * protoLfeReal + protoLfeImag * protoLfeImag; - - targetEneLfe = transportEne * hMasaLfeSynth->lfeToTotalEnergyRatio[subframe_index]; - targetEneTrans = transportEne * max( ( 1.0f - hMasaLfeSynth->lfeToTotalEnergyRatio[subframe_index] ), 0.01f ); - - hMasaLfeSynth->transportEneSmooth *= MCMASA_LFE_SYNTH_ALPHA; - hMasaLfeSynth->protoLfeEneSmooth *= MCMASA_LFE_SYNTH_ALPHA; - hMasaLfeSynth->targetEneLfeSmooth *= MCMASA_LFE_SYNTH_ALPHA; - hMasaLfeSynth->targetEneTransSmooth *= MCMASA_LFE_SYNTH_ALPHA; - - hMasaLfeSynth->transportEneSmooth += transportEne; - hMasaLfeSynth->protoLfeEneSmooth += protoLfeEne; - hMasaLfeSynth->targetEneLfeSmooth += targetEneLfe; - hMasaLfeSynth->targetEneTransSmooth += targetEneTrans; - - lfeGain = min( 1.0f, sqrtf( hMasaLfeSynth->targetEneLfeSmooth / ( EPSILON + hMasaLfeSynth->protoLfeEneSmooth ) ) ); - transportGain = min( 1.0f, sqrtf( hMasaLfeSynth->targetEneTransSmooth / ( EPSILON + hMasaLfeSynth->transportEneSmooth ) ) ); - - RealBufferLfe[slot_index][0] = protoLfeReal * lfeGain; - ImagBufferLfe[slot_index][0] = protoLfeImag * lfeGain; - - RealBuffer[0][0][0] *= transportGain; - ImagBuffer[0][0][0] *= transportGain; - for ( i = 1; i < nchan_transport; i++ ) - { - RealBuffer[i][0][0] *= transportGain; - ImagBuffer[i][0][0] *= transportGain; - } - - return; -} - - -/*------------------------------------------------------------------------- - * rotateAziEle_DirAC() - * - * Apply rotation to DirAC DOAs - *------------------------------------------------------------------------*/ - -void rotateAziEle_DirAC( - int16_t *azi, /* i/o: array of azimuth values */ - int16_t *ele, /* i/o: array of elevation values */ - const int16_t band1, /* i : bands to work on (lower limit) */ - const int16_t band2, /* i : bands to work on (upper bound) */ - const float *p_Rmat /* i : pointer to real-space rotation matrix */ -) -{ - int16_t b; - float dv_0, dv_1, dv_2; - float dv_r_0, dv_r_1, dv_r_2; - float w; - - push_wmops( "rotateAziEle_DirAC" ); - - for ( b = band1; b < band2; b++ ) - { - - /*Conversion spherical to cartesian coordinates*/ - w = cosf( ele[b] * PI_OVER_180 ); - dv_0 = w * cosf( azi[b] * PI_OVER_180 ); - dv_1 = w * sinf( azi[b] * PI_OVER_180 ); - dv_2 = sinf( ele[b] * PI_OVER_180 ); - - dv_r_0 = p_Rmat[0] * dv_0 + p_Rmat[1] * dv_1 + p_Rmat[2] * dv_2; - dv_r_1 = p_Rmat[3] * dv_0 + p_Rmat[4] * dv_1 + p_Rmat[5] * dv_2; - dv_r_2 = p_Rmat[6] * dv_0 + p_Rmat[7] * dv_1 + p_Rmat[8] * dv_2; - - /*Conversion spherical to cartesian coordinates*/ - azi[b] = (int16_t) ( atan2f( dv_r_1, dv_r_0 ) * _180_OVER_PI ); - ele[b] = (int16_t) ( atan2f( dv_r_2, sqrtf( dv_r_0 * dv_r_0 + dv_r_1 * dv_r_1 ) ) * _180_OVER_PI ); - } - - pop_wmops(); - - return; -} diff --git a/lib_rend/ivas_objectRenderer.c b/lib_rend/ivas_objectRenderer.c index 9748fe835b2ffc7e085d139aaf5d43a33cafd35f..0a6938254ac491fc1f80541c9681521d32d1a455 100644 --- a/lib_rend/ivas_objectRenderer.c +++ b/lib_rend/ivas_objectRenderer.c @@ -193,7 +193,12 @@ ivas_error ivas_td_binaural_open_unwrap( TDREND_MIX_SRC_SetDirAtten( pBinRendTd, nS, DirAtten_p ); } } + +#ifdef MASA_AND_OBJECTS + if ( ivas_format == ISM_FORMAT || ivas_format == MASA_ISM_FORMAT ) +#else if ( ivas_format == ISM_FORMAT ) +#endif { DirAtten_p = pBinRendTd->DirAtten_p; if ( NULL == directivity ) @@ -216,7 +221,15 @@ ivas_error ivas_td_binaural_open_unwrap( } *hBinRendererTd = pBinRendTd; + +#ifdef MASA_AND_OBJECTS + if ( ivas_format != MASA_ISM_FORMAT ) + { + *binaural_latency_ns = (int32_t) ( ( *hBinRendererTd )->HrFiltSet_p->latency_s * 1000000000.f ); + } +#else *binaural_latency_ns = (int32_t) ( ( *hBinRendererTd )->HrFiltSet_p->latency_s * 1000000000.f ); +#endif return error; } @@ -495,7 +508,11 @@ void TDREND_Update_object_positions( /* For each source, write the frame data to the source object*/ for ( nS = 0; nS < num_src; nS++ ) { +#ifdef MASA_AND_OBJECTS + if ( in_format == ISM_FORMAT || in_format == MASA_ISM_FORMAT ) +#else if ( in_format == ISM_FORMAT ) +#endif { /* Update the source positions */ /* Source position and direction */ diff --git a/lib_rend/ivas_prot_rend.h b/lib_rend/ivas_prot_rend.h index 2b2915d1941d192d3042e448df98735daca9f6d7..e64fdce77a4a23d07f8d2961a3b5e02ce997966d 100644 --- a/lib_rend/ivas_prot_rend.h +++ b/lib_rend/ivas_prot_rend.h @@ -37,7 +37,6 @@ #include "options.h" #include "ivas_error.h" #include "lib_rend.h" -#include "ivas_stat_rend.h" #include "ivas_stat_dec.h" // Note: needed until #156 is resolved /* clang-format off */ @@ -134,7 +133,7 @@ void efap_determine_gains( /*----------------------------------------------------------------------------------* - * DirAC/MASA rendering + * SBA rendering *----------------------------------------------------------------------------------*/ void ivas_sba_prototype_renderer( @@ -152,7 +151,7 @@ ivas_error ivas_sba_get_hoa_dec_matrix( #ifdef FIX_564 -void ivas_dirac_dec_binaural_sba_gain( +void ivas_dirac_dec_binaural_gain( float output[][L_FRAME48k], /* i/o: synthesized core-coder transport channels/DirAC output */ const int16_t nchan_remapped, /* i : num channels after remapping of TCs */ const int16_t output_frame /* i : output frame length */ @@ -188,323 +187,6 @@ ivas_error ivas_dirac_dec_binaural_copy_hrtfs( HRTFS_PARAMBIN_HANDLE *hHrtfParambin /* i/o: HRTF structure for rendering */ ); -/*! r: Configured reqularization factor value */ -float configure_reqularization_factor( - const IVAS_FORMAT ivas_format, /* i : IVAS format */ - const int32_t ivas_total_brate /* i : total IVAS bitrate */ -); - -ivas_error ivas_dirac_alloc_mem( - DIRAC_REND_HANDLE hDirACRend, - const RENDERER_TYPE renderer_type, - const int16_t num_freq_bands, - DIRAC_DEC_STACK_MEM_HANDLE hDirAC_mem, - const int16_t hodirac_flag -); - -void ivas_dirac_free_mem( - DIRAC_DEC_STACK_MEM_HANDLE hDirAC_mem -); - -void initDiffuseResponses( - float *diffuse_response_function, - const int16_t num_channels, - AUDIO_CONFIG output_config, - IVAS_OUTPUT_SETUP hOutSetup, - const int16_t ambisonics_order, - const IVAS_FORMAT ivas_format, - int16_t *num_ele_spk_no_diffuse_rendering, - AUDIO_CONFIG transport_config -); - -void computeIntensityVector_dec( - float Cldfb_RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], - float Cldfb_ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], - const int16_t num_frequency_bands, - float *intensity_real_x, - float *intensity_real_y, - float *intensity_real_z -); - -void protoSignalComputation_shd( - float RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], - float ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], - float *proto_direct_buffer_f, - float *proto_diffuse_buffer_f, - float *reference_power, - const int16_t slot_index, - const int16_t num_inputs, - const int16_t num_outputs_diff, - const int16_t num_freq_bands, - float *p_Rmat -); - -void protoSignalComputation1( - float RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], - float ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], - float *proto_frame_f, - float *proto_direct_buffer_f, - float *reference_power, - float *proto_power_smooth, - const int16_t slot_index, - const int16_t num_outputs_diff, - const int16_t num_freq_bands -); - -void protoSignalComputation2( - float RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], - float ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], - float *proto_frame_f, - float *proto_direct_buffer_f, - float *reference_power, - float *proto_power_smooth, - const int16_t isloudspeaker, - const int16_t slot_index, - const int16_t num_freq_bands, - MASA_STEREO_TYPE_DETECT *stereo_type_detect -); - -void protoSignalComputation4( - float RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], - float ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], - float *proto_frame_f, - float *proto_direct_buffer_f, - float *reference_power, - float *proto_power_smooth, - const int16_t slot_index, - const int16_t num_outputs_diff, - const int16_t num_freq_bands, - const - float *mtx_hoa_decoder, - const int16_t nchan_transport, - const int16_t *sba_map_tc_ind -); - -void ivas_dirac_dec_compute_diffuse_proto( - DIRAC_REND_HANDLE hDirACRend, - const int16_t num_freq_bands, - const int16_t slot_idx -); - -void computeDirectionAngles( - float *intensity_real_x, - float *intensity_real_y, - float *intensity_real_z, - const int16_t num_frequency_bands, - int16_t *azimuth, - int16_t *elevation -); - -void ivas_masa_init_stereotype_detection( - MASA_STEREO_TYPE_DETECT *stereo_type_detect -); - -void ivas_masa_stereotype_detection( - MASA_STEREO_TYPE_DETECT *stereo_type_detect -); - -void ivas_lfe_synth_with_cldfb( - MCMASA_LFE_SYNTH_DATA_HANDLE hMasaLfeSynth, - float RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], - float ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], - float RealBufferLfe[MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], - float ImagBufferLfe[MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], - const int16_t slot_index, - const int16_t subframe_index, - const int16_t nchan_transport -); - -void rotateAziEle_DirAC( - int16_t *azi, - int16_t *ele, - const int16_t band1, - const int16_t band2, - const float *p_Rmat -); - -ivas_error ivas_dirac_dec_onset_detection_open( - const int16_t num_channels, - const int16_t num_freq_bands, - const int16_t max_band_decorr, - DIRAC_ONSET_DETECTION_PARAMS *ph_dirac_onset_detection_params, - DIRAC_ONSET_DETECTION_STATE *ph_dirac_onset_detection_state -); - -void ivas_dirac_dec_onset_detection_process( - const float *input_power_f, - float *onset_filter, - const int16_t num_protos_diff, - DIRAC_ONSET_DETECTION_PARAMS h_dirac_onset_detection_params, - DIRAC_ONSET_DETECTION_STATE h_dirac_onset_detection_state -); - -ivas_error ivas_dirac_dec_decorr_open( - DIRAC_DECORR_PARAMS **ph_freq_domain_decorr_ap_params, - DIRAC_DECORR_STATE **ph_freq_domain_decorr_ap_state, - const int16_t num_freq_bands, - int16_t num_outputs_diff, - const int16_t num_protos_diff, - const DIRAC_SYNTHESIS_CONFIG synthesisConf, - float *frequency_axis, - const int16_t nchan_transport, /* i : number of transport channels */ - const int32_t output_Fs /* i : output sampling rate */ -); - -void ivas_dirac_dec_decorr_process( - const int16_t num_freq_bands, - int16_t num_channels, - const int16_t num_protos_diff, - const DIRAC_SYNTHESIS_CONFIG synthesisConf, - const int16_t nchan_transport, /* i : number of transport channels */ - const float *input_frame_f, - const int16_t num_protos_dir, - const int16_t *proto_index_dir, - float *frame_dec_f, - float *onset_filter, - HANDLE_DIRAC_DECORR_PARAMS h_freq_domain_decorr_ap_params, - HANDLE_DIRAC_DECORR_STATE h_freq_domain_decorr_ap_state -); - -void ivas_dirac_dec_decorr_close( - HANDLE_DIRAC_DECORR_PARAMS *ph_dirac_decorr_params, - HANDLE_DIRAC_DECORR_STATE *ph_dirac_decorr_state -); - -ivas_error ivas_dirac_dec_output_synthesis_open( - SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, /* i/o: common spatial renderer data handle */ - DIRAC_REND_HANDLE hDirACRend, /* i/o: DirAC renderer handle */ - const RENDERER_TYPE renderer_type, /* i : renderer type */ - const int16_t nchan_transport, /* i : number of transport channels */ - const int32_t output_Fs, /* i : output sampling rate */ - const int16_t hodirac_flag /* i : flag to indicate HO-DirAC mode */ -); - -void ivas_dirac_dec_output_synthesis_init( - SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, /* i/o: common spatial renderer data handle */ - DIRAC_REND_HANDLE hDirACRend, /* i/o: DirAC renderer handle */ - const int16_t nchan_out_woLFE, /* i : number of output audio channels without LFE */ - const int16_t hodirac_flag /* i : flag to indicate HO-DirAC mode */ -); - -void ivas_dirac_dec_output_synthesis_close( - DIRAC_REND_HANDLE hDirACRend /* i/o: DirAC handle */ -); - -void ivas_dirac_dec_output_synthesis_process_slot( - const float *reference_power, /* i : Estimated power */ - const float *onset, /* i : onset filter */ - const int16_t *azimuth, - const int16_t *elevation, - const float *diffuseness, - SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, /* i/o: common spatial renderer data handle */ - DIRAC_REND_HANDLE hDirACRend, /* i/o: DirAC renderer handle */ - const int16_t sh_rot_max_order, - const float *p_Rmat, /* i : rotation matrix */ - const VBAP_HANDLE hVBAPdata, /* i : VBAP structure */ - const IVAS_OUTPUT_SETUP hOutSetup, /* i : output setup structure */ - const int16_t nchan_transport, /* i : number of transport channels */ - const int16_t ind_slot, /* i : index of the slot to be added to the input covariance */ - const int16_t hodirac_flag, /* i : flag to indicate HO-DirAC mode */ - const int16_t dec_param_estim /* i : flag to indicate parameter estimation mode */ -); - -void ivas_dirac_dec_output_synthesis_process_subframe_gain_shd( - float RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX],/* i : LS signals */ - float ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX],/* i : LS signals */ - SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, /* i/o: common spatial renderer data handle */ - DIRAC_REND_HANDLE hDirACRend, /* i/o: DirAC renderer handle */ - const int16_t nchan_transport, /* i : number of transport channels */ - const int16_t nbslots, /* i : number of slots to process */ - const float *onset_filter, - float *diffuseness, - const int16_t hodirac_flag, /* i : flag to indicate HO-DirAC mode */ - const int16_t dec_param_estim /* i : flag to indicate parameter estimation mode */ -); - -void ivas_dirac_dec_output_synthesis_process_subframe_psd_ls( - float RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX],/* i : LS signals */ - float ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX],/* i : LS signals */ - SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, /* i/o: common spatial renderer data handle */ - DIRAC_REND_HANDLE hDirACRend, /* i/o: DirAC renderer handle */ - const int16_t nbslots, /* i : number of slots to process */ - float *diffuseness_vector, /* i : diffuseness (needed for direction smoothing)*/ - float *reference_power_smooth, - float qualityBasedSmFactor, - const int16_t enc_param_start_band -); - -void compute_hoa_encoder_mtx( - const float *azimuth, - const float *elevation, - float *response, - const int16_t num_responses, - const int16_t ambisonics_order ); - -void ivas_dirac_dec_compute_gain_factors( - const int16_t num_freq_bands, - const float *diffuseness, - const int16_t max_band_decorr, - float *direct_gain_factor, - float *diffuse_gain_factor -); - -void ivas_dirac_dec_compute_power_factors( - const int16_t num_freq_bands, - const float *diffuseness, - const int16_t max_band_decorr, - float *direct_power_factor, - float *diffuse_power_factor -); - -void ivas_dirac_dec_compute_directional_responses( - SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, /* i/o: common spatial renderer data handle */ - DIRAC_REND_HANDLE hDirACRend, /* i/o: DirAC renderer handle */ - const VBAP_HANDLE hVBAPdata, /* i : VBAP structure */ - const MASA_DECODER_HANDLE hMasa, /* i : MASA decoder structure */ - const int16_t *azimuth, - const int16_t *elevation, - const int16_t md_idx, - const float *surCohRatio, - const int16_t shd_rot_max_order, /* i : split-order rotation method */ - const float *p_Rmat, /* i : rotation matrix */ - const int16_t hodirac_flag /* i : flag to indicate HO-DirAC mode */ -); - -void ivas_dirac_dec_get_frequency_axis( - float *frequency_axis, /* o : array of center frequencies of a real filter bank */ - const int32_t output_Fs, /* i : sampling frequency */ - const int16_t num_freq_bands /* i : number of frequency bands */ -); - -ivas_error ivas_spat_hSpatParamRendCom_config( - SPAT_PARAM_REND_COMMON_DATA_HANDLE *hSpatParamRendCom_out, /* i/o: IVAS decoder structure */ - const DIRAC_CONFIG_FLAG flag_config_inp, /* i/ : Flag determining if we open or reconfigure the DirAC decoder */ - const int16_t dec_param_estim_flag, - const IVAS_FORMAT ivas_format, - const MC_MODE mc_mode, - const int32_t output_Fs, - const int16_t hodirac_flag -); - -void ivas_spat_hSpatParamRendCom_close( - SPAT_PARAM_REND_COMMON_DATA_HANDLE *hSpatParamRendCom_out -); - -void ivas_dirac_rend_close( - DIRAC_REND_HANDLE *hDirACRend_out -); - -ivas_error ivas_dirac_allocate_parameters( - SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, /* i/o: common data for spatial parametric rendering */ - const int16_t params_flag /* i : set of parameters flag */ -); - -void ivas_dirac_deallocate_parameters( - SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, /* i/o: common data for spatial parametric rendering */ - const int16_t params_flag /* i : set of parameters flag */ -); - - /*----------------------------------------------------------------------------------* * HRTF diff --git a/lib_rend/ivas_rotation.c b/lib_rend/ivas_rotation.c index c7d372d65d5ae08c6bbd7103f35008dfed804224..a3bf1f1d922f322aa99982283455a58a7c8d5cb7 100644 --- a/lib_rend/ivas_rotation.c +++ b/lib_rend/ivas_rotation.c @@ -225,11 +225,17 @@ void Quat2EulerDegree( { if ( quat.w != -3.0 ) { +#ifdef EULER2QUAT_FIX float p; +#endif *yaw = atan2f( 2 * ( quat.w * quat.x + quat.y * quat.z ), 1 - 2 * ( quat.x * quat.x + quat.y * quat.y ) ); +#ifdef EULER2QUAT_FIX p = 2 * ( quat.w * quat.y - quat.z * quat.x ); p = max( -1.0f, min( 1.0f, p ) ); *pitch = asinf( p ); +#else + *pitch = asinf( 2 * ( quat.w * quat.y - quat.z * quat.x ) ); +#endif *roll = atan2f( 2 * ( quat.w * quat.z + quat.x * quat.y ), 1 - 2 * ( quat.y * quat.y + quat.z * quat.z ) ); *yaw *= _180_OVER_PI; *pitch *= _180_OVER_PI; diff --git a/lib_rend/ivas_stat_rend.h b/lib_rend/ivas_stat_rend.h index 36c4a1783654583e146ceeaa66ccc38ad58840d6..40d8127437311b9047e668ef0f2940471676e652 100644 --- a/lib_rend/ivas_stat_rend.h +++ b/lib_rend/ivas_stat_rend.h @@ -47,7 +47,6 @@ #include "ivas_lc3plus_dec.h" #endif -//#include "ivas_stat_dec.h" /*----------------------------------------------------------------------------------* * Output configuration for renderer (e.g. DirAC, MASA, Binaural Renderer...) @@ -73,348 +72,6 @@ typedef struct ivas_output_setup_structure } IVAS_OUTPUT_SETUP, *IVAS_OUTPUT_SETUP_HANDLE; -/*----------------------------------------------------------------------------------* - * Spatial parametric rendering common structures - *----------------------------------------------------------------------------------*/ - -/*Onset detector*/ -typedef struct dirac_onset_detection_params_structure -{ - int16_t num_freq_bands; - int16_t max_band_decorr; - -} DIRAC_ONSET_DETECTION_PARAMS; - -typedef struct dirac_onset_detection_state_structure -{ - float *onset_detector_1; - float *onset_detector_2; - -} DIRAC_ONSET_DETECTION_STATE; - -/*Decorrelator*/ -typedef struct dirac_decorr_params_structure -{ - int16_t max_band_decorr; - int16_t max_frequency; - - int16_t *pre_delay; - int16_t *filter_length; - float *filter_coeff_num_real; - float *filter_coeff_den_real; - float *phase_coeff_real; - float *phase_coeff_imag; - int16_t *split_frequency_bands; - int16_t num_split_frequency_bands; - - int16_t use_ducker; - int16_t add_back_onsets_on; - - DIRAC_ONSET_DETECTION_PARAMS h_onset_detection_power_params; - -} DIRAC_DECORR_PARAMS, *HANDLE_DIRAC_DECORR_PARAMS; - -typedef struct dirac_decorr_state_structure -{ - float *decorr_buffer; - float *direct_energy_smooth; - float *reverb_energy_smooth; - - DIRAC_ONSET_DETECTION_STATE h_onset_detection_power_state; - -} DIRAC_DECORR_STATE, *HANDLE_DIRAC_DECORR_STATE; - -typedef struct ivas_spatial_parametric_rend_common_data_structure -{ - int16_t slot_size; - int16_t subframe_nbslots[MAX_JBM_SUBFRAMES_5MS]; - int16_t subframes_rendered; - int16_t slots_rendered; - int16_t num_slots; - int16_t render_to_md_map[MAX_JBM_SUBFRAMES_5MS * JBM_CLDFB_SLOTS_IN_SUBFRAME]; - int16_t nb_subframes; - - int16_t num_freq_bands; - int16_t numSimultaneousDirections; /* 1 or 2 */ - - int16_t **azimuth; - int16_t **elevation; - int16_t **azimuth2; - int16_t **elevation2; - - float **diffuseness_vector; - float **energy_ratio1; - float **energy_ratio2; - - float **spreadCoherence; - float **spreadCoherence2; - float **surroundingCoherence; - - /* Metadata access indices and buffer size */ - int16_t dirac_bs_md_write_idx; - int16_t dirac_read_idx; - int16_t dirac_md_buffer_length; - -} SPAT_PARAM_REND_COMMON_DATA, *SPAT_PARAM_REND_COMMON_DATA_HANDLE; - - -/*----------------------------------------------------------------------------------* - * DirAC rendering structures - *----------------------------------------------------------------------------------*/ - -typedef struct dirac_dec_stack_mem -{ - /*Decorrelator*/ - float *frame_dec_f; - - /*Prototypes*/ - float *proto_direct_buffer_f; - float *proto_diffuse_buffer_f; - - /*Prototype NRGs*/ - float *proto_power_smooth; - float *proto_power_diff_smooth; - - /*Gain or power factors for directional and diffuse streams*/ - float *direct_power_factor; - float *diffuse_power_factor; - - /*Directional responses (gains & Nrg)*/ - float *direct_responses; - float *direct_responses_square; - - /* Target co-variance mtx */ - float *cy_auto_dir_smooth; - float *cy_cross_dir_smooth; - float *cy_auto_diff_smooth; - - float *reference_power; - float *onset_filter; - -} DIRAC_DEC_STACK_MEM, *DIRAC_DEC_STACK_MEM_HANDLE; - -/*Output synthesis*/ -typedef struct dirac_output_synthesis_params_structure -{ - int16_t max_band_decorr; - - int16_t use_onset_filters; - - float *interpolator; - float *alpha_synthesis; - float *alpha_synthesis_fast; - int16_t numAlphas; - int16_t numAlphasFast; - - float *proto_matrix; - - float diffuse_compensation_factor; - float diffuse_compensation_factor_decorr; - -} DIRAC_OUTPUT_SYNTHESIS_PARAMS; - -typedef struct dirac_output_synthesis_state_structure -{ - /* only pointer to local buffers */ - float *direct_responses; /* direct responses for DOA of current frame. Size: num_freq_bands*num_channels. */ - float *direct_responses_square; - float *diffuse_responses_square; /* squared diffuse responses. Size: num_channels. */ - - /* only pointer to local buffers */ - float *direct_power_factor; - float *diffuse_power_factor; - - float *proto_power_smooth; /* Smoothed power of the prototype signals. Size: num_freq_bands*num_channels. */ - float *proto_power_smooth_prev; /* Smoothed power of the prototype signals of the previous synthesis block. Size: num_freq_bands*num_channels. */ - - float *proto_power_diff_smooth; - float *proto_power_diff_smooth_prev; - - /* only pointer to local buffers */ - float *proto_direct_buffer_f; /* Buffer for direct sound prototype signals. Size: 2*num_freq_bands*num_channels*buffer_length (complex interleaved). */ - float *proto_diffuse_buffer_f; /* Buffer for diffuse sound prototype signals. Size: 2*num_freq_bands*num_channels*buffer_length (complex interleaved). */ - - /* Output gain memories */ - float *gains_dir_prev; /* Direct sound gains of current synthesis block. Size: num_freq_bands*num_channel. */ - float *gains_diff_prev; /* Diffuse sound gains of previous synthesis block. Size: num_freq_bands*num_channel. */ - - /* only pointer to local buffers */ - float *cy_auto_dir_smooth; /* Target auto PSD of direct sound. Size: num_freq_bands*num_channels. */ - float *cy_cross_dir_smooth; /* Target cross PSD of direct sound. Size: num_freq_bands*num_channels. */ - float *cy_auto_diff_smooth; /* Target auto PSD of diffuse sound. Size: num_freq_bands*num_channels. */ - - /* PSD memories */ - float *cy_auto_dir_smooth_prev; /* Target auto PSD of direct sound of previous synthesis block. Size: num_freq_bands*num_channels. */ - float *cy_cross_dir_smooth_prev; /* Target cross PSD of direct sound of previous synthesis block. Size: num_freq_bands*num_channels. */ - float *cy_auto_diff_smooth_prev; /* Target auto PSD of diffuse sound of previous synthesis block. Size: num_freq_bands*num_channels. */ - - const float *onset_filter; - - /* Temporal smoothing memories */ - float *reference_power_smooth_prev; - float *direction_smoothness_prev; - -} DIRAC_OUTPUT_SYNTHESIS_STATE; - -/* MASA stereo transport signal type detection structure */ -typedef struct -{ - MASA_TRANSPORT_SIGNAL_TYPE masa_stereo_type; - MASA_TRANSPORT_SIGNAL_TYPE current_stereo_type; - MASA_TRANSPORT_SIGNAL_TYPE type_change_direction; - - int16_t dipole_freq_range[2]; - - float left_bb_power; - float right_bb_power; - float total_bb_power; - - float left_hi_power; - float right_hi_power; - float total_hi_power; - - float sum_power[MASA_SUM_FREQ_RANGE_BINS]; - float total_power[MASA_SUM_FREQ_RANGE_BINS]; - - float subtract_power_y; - float subtract_power_y_smooth; - float target_power_y_smooth; - - float lr_total_bb_ratio_db; - float lr_total_hi_ratio_db; - float min_sum_total_ratio_db; - float subtract_target_ratio_db; - - int16_t counter; - int16_t interpolator; - -} MASA_STEREO_TYPE_DETECT; - -/* McMASA LFE synthesis structure */ -typedef struct ivas_mcmasa_lfe_synth_struct -{ - float lfeToTotalEnergyRatio[MAX_PARAM_SPATIAL_SUBFRAMES]; - int16_t lfeGainPrevIndex; - float transportEneSmooth; - float protoLfeEneSmooth; - float targetEneLfeSmooth; - float targetEneTransSmooth; - - float *lfeSynthRingBuffer; - int16_t ringBufferLoPointer; - int16_t ringBufferHiPointer; - float lowpassSum; - int16_t ringBufferSize; - - float *lfeSynthRingBuffer2; - int16_t ringBufferLoPointer2; - float lowpassSum2; - int16_t ringBufferSize2; - - float *delayBuffer_syncLp; - int16_t delayBuffer_syncLp_size; - - float *delayBuffer_syncDirAC; - int16_t delayBuffer_syncDirAC_size; - - float lfeGainPrev; - float transportGainPrev; - float interpolator[CLDFB_NO_CHANNELS_MAX]; - -} MCMASA_LFE_SYNTH_DATA, *MCMASA_LFE_SYNTH_DATA_HANDLE; - -/* DirAC renderer main structure */ -typedef struct ivas_dirac_rend_data_structure -{ - IVAS_OUTPUT_SETUP hOutSetup; - - /*Parameter estimation*/ - int16_t index_buffer_intensity; - float *buffer_intensity_real[DIRAC_NUM_DIMS][DIRAC_NO_COL_AVG_DIFF]; - float *buffer_energy; - - float *frequency_axis; - float *diffuse_response_function; - float *hoa_encoder; - const float *hoa_decoder; - - /*Decoder parameters */ - /*Prototypes*/ - int16_t num_outputs_dir; - int16_t num_outputs_diff; - int16_t num_protos_dir; - int16_t num_protos_diff; - int16_t num_protos_ambi; - DIRAC_SYNTHESIS_CONFIG synthesisConf; - DIRAC_PANNING_CONFIG panningConf; - - /* prototype computing */ - int16_t *proto_index_dir; - int16_t *proto_index_diff; - - int16_t proto_signal_decorr_on; - - /*Decoder states=memories*/ - float *proto_frame_f; - float *proto_frame_dec_f; - - DIRAC_DEC_STACK_MEM stack_mem; - MASA_STEREO_TYPE_DETECT *masa_stereo_type_detect; - - int16_t num_ele_spk_no_diffuse_rendering; - - const int16_t *sba_map_tc; - - DIRAC_OUTPUT_SYNTHESIS_PARAMS h_output_synthesis_psd_params; - DIRAC_OUTPUT_SYNTHESIS_STATE h_output_synthesis_psd_state; - - HANDLE_DIRAC_DECORR_PARAMS h_freq_domain_decorr_ap_params; - HANDLE_DIRAC_DECORR_STATE h_freq_domain_decorr_ap_state; - -} DIRAC_REND_DATA, *DIRAC_REND_HANDLE; - - -/*----------------------------------------------------------------------------------* - * VBAP structures - *----------------------------------------------------------------------------------*/ - -/* Defines a single virtual surface triplet of loudspeakers - * with a precalculated inverse matrix */ -typedef struct vbap_vs_triplet_structure -{ - uint8_t speaker_node[3]; - float inverse_matrix[3][3]; - -} VBAP_VS_TRIPLET; - - -/* Storage structure for fast runtime triplet search */ -typedef struct triplet_search_structure -{ - VBAP_VS_TRIPLET *triplets; - int16_t num_triplets; - int16_t initial_search_indices[VBAP_NUM_SEARCH_SECTORS]; - -} VBAP_SEARCH_STRUCT; - - -/* VBAP data structure. Contains the formed virtual surface arrangement * and supporting data. */ -typedef struct vbap_data_structure -{ - VBAP_SEARCH_STRUCT search_struct[2]; /* Default to max two groups in this implementation */ - int16_t num_search_structs; - int16_t num_speaker_nodes; - int16_t num_speaker_nodes_internal; - int16_t top_virtual_speaker_node_index; /* These indices can be negative */ - int16_t bottom_virtual_speaker_node_index; - int16_t back_virtual_speaker_node_index; - float *bottom_virtual_speaker_node_division_gains; - float *top_virtual_speaker_node_division_gains; - float *back_virtual_speaker_node_division_gains; - -} VBAP_DATA, *VBAP_HANDLE; - - /*----------------------------------------------------------------------------------* * Binaural FastConv Rendering structure *----------------------------------------------------------------------------------*/ @@ -457,17 +114,6 @@ typedef struct ivas_binaural_reverb_struct } REVERB_STRUCT, *REVERB_STRUCT_HANDLE; - -/* Diffuse sound directional distribution data structure */ -typedef struct ivas_diffuse_distribution_data_structure -{ - float diffuseRatioX[CLDFB_NO_CHANNELS_MAX]; - float diffuseRatioY[CLDFB_NO_CHANNELS_MAX]; - float diffuseRatioZ[CLDFB_NO_CHANNELS_MAX]; - -} DIFFUSE_DISTRIBUTION_DATA, *DIFFUSE_DISTRIBUTION_HANDLE; - - /* Parametric binaural data structure */ typedef struct ivas_dirac_dec_binaural_data_structure { @@ -483,8 +129,13 @@ typedef struct ivas_dirac_dec_binaural_data_structure float ChEneOut[BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX]; float ChCrossReOut[CLDFB_NO_CHANNELS_MAX]; float ChCrossImOut[CLDFB_NO_CHANNELS_MAX]; +#ifdef MASA_AND_OBJECTS + float processMtxRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS + MAX_NUM_OBJECTS][CLDFB_NO_CHANNELS_MAX]; + float processMtxIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS + MAX_NUM_OBJECTS][CLDFB_NO_CHANNELS_MAX]; +#else float processMtxRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS + 1][CLDFB_NO_CHANNELS_MAX]; /* +1 refers to SeparateChannel */ float processMtxIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS + 1][CLDFB_NO_CHANNELS_MAX]; +#endif float processMtxDecRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX]; float processMtxDecIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX]; float diffuseFieldCoherence[CLDFB_NO_CHANNELS_MAX]; @@ -495,19 +146,20 @@ typedef struct ivas_dirac_dec_binaural_data_structure REVERB_STRUCT_HANDLE hReverb; uint8_t renderStereoOutputInsteadOfBinaural; float frameMeanDiffuseness[CLDFB_NO_CHANNELS_MAX]; +#ifdef MASA_AND_OBJECTS + float processMtxRePrev[BINAURAL_CHANNELS][BINAURAL_CHANNELS + MAX_NUM_OBJECTS][CLDFB_NO_CHANNELS_MAX]; + float processMtxImPrev[BINAURAL_CHANNELS][BINAURAL_CHANNELS + MAX_NUM_OBJECTS][CLDFB_NO_CHANNELS_MAX]; +#else float processMtxRePrev[BINAURAL_CHANNELS][BINAURAL_CHANNELS + 1][CLDFB_NO_CHANNELS_MAX]; float processMtxImPrev[BINAURAL_CHANNELS][BINAURAL_CHANNELS + 1][CLDFB_NO_CHANNELS_MAX]; +#endif float processMtxDecRePrev[BINAURAL_CHANNELS][BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX]; float processMtxDecImPrev[BINAURAL_CHANNELS][BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX]; + uint16_t useSubframeMode; /* 0 = process in 20 ms frames, 1 = process in 5 ms subframes */ uint16_t useTdDecorr; ivas_td_decorr_state_t *hTdDecorr; float reqularizationFactor; - DIFFUSE_DISTRIBUTION_HANDLE hDiffuseDist; - - HANDLE_DIRAC_DECORR_PARAMS h_freq_domain_decorr_ap_params; - HANDLE_DIRAC_DECORR_STATE h_freq_domain_decorr_ap_state; - } DIRAC_DEC_BIN_DATA, *DIRAC_DEC_BIN_HANDLE; typedef struct ivas_binaural_rendering_conv_module_struct diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 9509f11bc5b13bb8adbce9f8c08ea5b0b702fd20..6ad462c7114122d02f0c86467a4563fb94397862 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -57,9 +57,13 @@ /* Maximum buffer length (total) in samples. */ #ifdef SPLIT_REND_WITH_HEAD_ROT +#ifdef REND_STATIC_MEM_OPT #define MAX_BUFFER_LENGTH ( MAX_BUFFER_LENGTH_PER_CHANNEL * MAX_INPUT_CHANNELS ) #define MAX_CLDFB_BUFFER_LENGTH ( MAX_CLDFB_BUFFER_LENGTH_PER_CHANNEL * MAX_INPUT_CHANNELS ) #define MAX_BIN_BUFFER_LENGTH ( MAX_BUFFER_LENGTH_PER_CHANNEL * BINAURAL_CHANNELS ) +#else /* REND_STATIC_MEM_OPT */ +#define MAX_BUFFER_LENGTH ( MAX_CLDFB_BUFFER_LENGTH_PER_CHANNEL * MAX_INPUT_CHANNELS ) +#endif /* REND_STATIC_MEM_OPT */ #else #define MAX_BUFFER_LENGTH ( MAX_BUFFER_LENGTH_PER_CHANNEL * MAX_INPUT_CHANNELS ) @@ -120,6 +124,9 @@ typedef struct IVAS_REND_AudioConfig inConfig; IVAS_REND_InputId id; IVAS_REND_AudioBuffer inputBuffer; +#ifndef REND_STATIC_MEM_OPT + float bufferData[MAX_BUFFER_LENGTH]; +#endif float gain; /* Linear, not in dB */ rendering_context ctx; int32_t numNewSamplesPerChannel; /* Used to keep track how much new audio was fed before rendering current frame */ @@ -137,7 +144,9 @@ typedef struct #ifdef SPLIT_REND_WITH_HEAD_ROT TDREND_WRAPPER splitTdRendWrappers[MAX_HEAD_ROT_POSES - 1]; /* Additional TD Rend instances used for split rendering */ #endif +#ifdef REND_STATIC_MEM_OPT float *bufferData; +#endif int16_t nonDiegeticPan; float nonDiegeticPanGain; OMASA_ANA_HANDLE hOMasa; @@ -174,7 +183,9 @@ typedef struct int16_t nonDiegeticPan; float nonDiegeticPanGain; lfe_routing lfeRouting; +#ifdef REND_STATIC_MEM_OPT float *bufferData; +#endif MCMASA_ANA_HANDLE hMcMasa; } input_mc; @@ -192,7 +203,9 @@ typedef struct rotation_gains rot_gains_prev; #endif +#ifdef REND_STATIC_MEM_OPT float *bufferData; +#endif DIRAC_ANA_HANDLE hDirAC; } input_sba; @@ -201,7 +214,9 @@ typedef struct { input_base base; SPLIT_POST_REND_WRAPPER splitPostRendWrapper; +#ifdef REND_STATIC_MEM_OPT float *bufferData; +#endif } input_split_post_rend; #endif @@ -215,7 +230,9 @@ typedef struct DecoderDummy *decDummy; MASA_METADATA_FRAME masaMetadata; bool metadataHasBeenFed; +#ifdef REND_STATIC_MEM_OPT float *bufferData; +#endif MASA_PREREND_HANDLE hMasaPrerend; } input_masa; @@ -264,6 +281,7 @@ struct IVAS_REND * Local functions *-------------------------------------------------------------------*/ +#ifdef REND_STATIC_MEM_OPT static ivas_error allocateInputBaseBufferData( float **data, const int16_t data_size ) { *data = (float *) malloc( data_size * sizeof( float ) ); @@ -285,6 +303,7 @@ static void freeInputBaseBufferData( float **data ) return; } +#endif static IVAS_QUATERNION quaternionInit( void ) @@ -1201,9 +1220,13 @@ static void initRendInputBase( input_base *inputBase, const IVAS_REND_AudioConfig inConfig, const IVAS_REND_InputId id, - const rendering_context rendCtx, + const rendering_context rendCtx +#ifdef REND_STATIC_MEM_OPT + , float *dataBuf, - const int16_t dataBufSize ) + const int16_t dataBufSize +#endif +) { inputBase->inConfig = inConfig; inputBase->id = id; @@ -1213,11 +1236,17 @@ static void initRendInputBase( inputBase->inputBuffer.config.numSamplesPerChannel = 0; inputBase->inputBuffer.config.numChannels = 0; +#ifndef REND_STATIC_MEM_OPT + inputBase->inputBuffer.data = inputBase->bufferData; + + set_zero( inputBase->bufferData, MAX_BUFFER_LENGTH ); +#else inputBase->inputBuffer.data = dataBuf; if ( inputBase->inputBuffer.data != NULL ) { set_zero( inputBase->inputBuffer.data, dataBufSize ); } +#endif return; } @@ -1357,12 +1386,18 @@ static ivas_error setRendInputActiveIsm( return IVAS_ERR_IO_CONFIG_PAIR_NOT_SUPPORTED; } +#ifdef REND_STATIC_MEM_OPT if ( ( error = allocateInputBaseBufferData( &inputIsm->bufferData, MAX_BUFFER_LENGTH ) ) != IVAS_ERR_OK ) { return error; } - initRendInputBase( &inputIsm->base, inConfig, id, rendCtx, - inputIsm->bufferData, MAX_BUFFER_LENGTH ); +#endif + initRendInputBase( &inputIsm->base, inConfig, id, rendCtx +#ifdef REND_STATIC_MEM_OPT + , + inputIsm->bufferData, MAX_BUFFER_LENGTH +#endif + ); inputIsm->currentPos = defaultObjectPosition(); inputIsm->previousPos = defaultObjectPosition(); @@ -1462,9 +1497,15 @@ static void clearInputIsm( rendCtx = inputIsm->base.ctx; +#ifdef REND_STATIC_MEM_OPT freeInputBaseBufferData( &inputIsm->base.inputBuffer.data ); - initRendInputBase( &inputIsm->base, IVAS_REND_AUDIO_CONFIG_UNKNOWN, 0, rendCtx, - NULL, 0 ); +#endif + initRendInputBase( &inputIsm->base, IVAS_REND_AUDIO_CONFIG_UNKNOWN, 0, rendCtx +#ifdef REND_STATIC_MEM_OPT + , + NULL, 0 +#endif + ); /* Free input's internal handles */ @@ -2367,12 +2408,18 @@ static ivas_error setRendInputActiveMc( return IVAS_ERR_IO_CONFIG_PAIR_NOT_SUPPORTED; } +#ifdef REND_STATIC_MEM_OPT if ( ( error = allocateInputBaseBufferData( &inputMc->bufferData, MAX_BUFFER_LENGTH ) ) != IVAS_ERR_OK ) { return error; } - initRendInputBase( &inputMc->base, inConfig, id, rendCtx, - inputMc->bufferData, MAX_BUFFER_LENGTH ); +#endif + initRendInputBase( &inputMc->base, inConfig, id, rendCtx +#ifdef REND_STATIC_MEM_OPT + , + inputMc->bufferData, MAX_BUFFER_LENGTH +#endif + ); setZeroPanMatrix( inputMc->panGains ); inputMc->customLsInput = defaultCustomLs(); inputMc->tdRendWrapper = defaultTdRendWrapper(); @@ -2425,9 +2472,15 @@ static void clearInputMc( rendCtx = inputMc->base.ctx; +#ifdef REND_STATIC_MEM_OPT freeInputBaseBufferData( &inputMc->bufferData ); - initRendInputBase( &inputMc->base, IVAS_REND_AUDIO_CONFIG_UNKNOWN, 0, rendCtx, - NULL, 0 ); +#endif + initRendInputBase( &inputMc->base, IVAS_REND_AUDIO_CONFIG_UNKNOWN, 0, rendCtx +#ifdef REND_STATIC_MEM_OPT + , + NULL, 0 +#endif + ); /* Free input's internal handles */ if ( inputMc->efapInWrapper.hEfap != NULL ) @@ -2724,12 +2777,18 @@ static ivas_error setRendInputActiveSplitPostRend( rendCtx = inputSplitPostRend->base.ctx; outConfig = *rendCtx.pOutConfig; +#ifdef REND_STATIC_MEM_OPT if ( ( error = allocateInputBaseBufferData( &inputSplitPostRend->bufferData, MAX_BIN_BUFFER_LENGTH ) ) != IVAS_ERR_OK ) { return error; } - initRendInputBase( &inputSplitPostRend->base, inConfig, id, rendCtx, - inputSplitPostRend->bufferData, MAX_BIN_BUFFER_LENGTH ); +#endif + initRendInputBase( &inputSplitPostRend->base, inConfig, id, rendCtx +#ifdef REND_STATIC_MEM_OPT + , + inputSplitPostRend->bufferData, MAX_BIN_BUFFER_LENGTH +#endif + ); if ( ( error = updateSplitPostRendPanGains( inputSplitPostRend, outConfig, hRendCfg ) ) != IVAS_ERR_OK ) { @@ -2783,6 +2842,7 @@ static ivas_error setRendInputActiveSba( return IVAS_ERR_IO_CONFIG_PAIR_NOT_SUPPORTED; } +#ifdef REND_STATIC_MEM_OPT #ifdef SPLIT_REND_WITH_HEAD_ROT if ( ( error = allocateInputBaseBufferData( &inputSba->bufferData, MAX_CLDFB_BUFFER_LENGTH ) ) != IVAS_ERR_OK ) #else @@ -2796,6 +2856,9 @@ static ivas_error setRendInputActiveSba( #else initRendInputBase( &inputSba->base, inConfig, id, rendCtx, inputSba->bufferData, MAX_BUFFER_LENGTH ); #endif /* SPLIT_REND_WITH_HEAD_ROT */ +#else /* REND_STATIC_MEM_OPT */ + initRendInputBase( &inputSba->base, inConfig, id, rendCtx ); +#endif /* REND_STATIC_MEM_OPT */ setZeroPanMatrix( inputSba->hoaDecMtx ); #ifdef SPLIT_REND_WITH_HEAD_ROT inputSba->crendWrapper = NULL; @@ -2833,9 +2896,15 @@ static void clearInputSplitRend( rendCtx = inputSplitRend->base.ctx; +#ifdef REND_STATIC_MEM_OPT freeInputBaseBufferData( &inputSplitRend->bufferData ); - initRendInputBase( &inputSplitRend->base, IVAS_REND_AUDIO_CONFIG_UNKNOWN, 0, rendCtx, - NULL, 0 ); +#endif + initRendInputBase( &inputSplitRend->base, IVAS_REND_AUDIO_CONFIG_UNKNOWN, 0, rendCtx +#ifdef REND_STATIC_MEM_OPT + , + NULL, 0 +#endif + ); if ( inputSplitRend->splitPostRendWrapper.hBinHrSplitPostRend != NULL ) { ivas_splitBinPostRendClose( &inputSplitRend->splitPostRendWrapper.hBinHrSplitPostRend ); @@ -2860,9 +2929,15 @@ static void clearInputSba( rendCtx = inputSba->base.ctx; +#ifdef REND_STATIC_MEM_OPT freeInputBaseBufferData( &inputSba->bufferData ); - initRendInputBase( &inputSba->base, IVAS_REND_AUDIO_CONFIG_UNKNOWN, 0, rendCtx, - NULL, 0 ); +#endif + initRendInputBase( &inputSba->base, IVAS_REND_AUDIO_CONFIG_UNKNOWN, 0, rendCtx +#ifdef REND_STATIC_MEM_OPT + , + NULL, 0 +#endif + ); /* Free input's internal handles */ #ifdef SPLIT_REND_WITH_HEAD_ROT @@ -2919,11 +2994,11 @@ static ivas_error initMasaDummyDecForMcOut( } decDummy->hQMetaData->coherence_flag = 1; - if ( ( error = ivas_dirac_dec_config( decDummy, DIRAC_OPEN ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_dirac_dec_open( decDummy ) ) != IVAS_ERR_OK ) { return error; } - decDummy->hSpatParamRendCom->dirac_bs_md_write_idx = 0; + decDummy->hDirAC->dirac_bs_md_write_idx = 0; if ( decDummy->renderer_type == RENDERER_STEREO_PARAMETRIC ) { @@ -2997,11 +3072,11 @@ static ivas_error initMasaDummyDecForSbaOut( } decDummy->hQMetaData->coherence_flag = 1; - if ( ( error = ivas_dirac_dec_config( decDummy, DIRAC_OPEN ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_dirac_dec_open( decDummy ) ) != IVAS_ERR_OK ) { return error; } - decDummy->hSpatParamRendCom->dirac_bs_md_write_idx = 0; + decDummy->hDirAC->dirac_bs_md_write_idx = 0; numCldfbAnalyses = decDummy->nchan_transport; numCldfbSyntheses = decDummy->hDecoderConfig->nchan_out; @@ -3071,11 +3146,11 @@ static ivas_error initMasaDummyDecForBinauralOut( decDummy->ivas_format = MASA_FORMAT; decDummy->transport_config = AUDIO_CONFIG_INVALID; - if ( ( error = ivas_dirac_dec_config( decDummy, DIRAC_OPEN ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_dirac_dec_open( decDummy ) ) != IVAS_ERR_OK ) { return error; } - decDummy->hSpatParamRendCom->dirac_bs_md_write_idx = 0; + decDummy->hDirAC->dirac_bs_md_write_idx = 0; if ( ( error = ivas_dirac_dec_binaural_copy_hrtfs( &decDummy->hHrtfParambin ) ) != IVAS_ERR_OK ) { @@ -3170,8 +3245,6 @@ static DecoderDummy *initDecoderDummy( decDummy->hVBAPdata = NULL; // note: not used at the moment decDummy->hMasa = NULL; decDummy->hDiracDecBin = NULL; - decDummy->hDirACRend = NULL; - decDummy->hSpatParamRendCom = NULL; decDummy->hQMetaData = NULL; decDummy->hHrtfParambin = NULL; decDummy->hHeadTrackData = NULL; @@ -3266,12 +3339,18 @@ static ivas_error setRendInputActiveMasa( return IVAS_ERR_IO_CONFIG_PAIR_NOT_SUPPORTED; } +#ifdef REND_STATIC_MEM_OPT if ( ( error = allocateInputBaseBufferData( &inputMasa->bufferData, MAX_BUFFER_LENGTH ) ) != IVAS_ERR_OK ) { return error; } - initRendInputBase( &inputMasa->base, inConfig, id, rendCtx, - inputMasa->bufferData, MAX_BUFFER_LENGTH ); +#endif + initRendInputBase( &inputMasa->base, inConfig, id, rendCtx +#ifdef REND_STATIC_MEM_OPT + , + inputMasa->bufferData, MAX_BUFFER_LENGTH +#endif + ); if ( ( error = getAudioConfigNumChannels( inConfig, &numInChannels ) ) != IVAS_ERR_OK ) { @@ -3353,8 +3432,6 @@ static void freeDecoderDummy( } /* DirAC handle */ - ivas_dirac_rend_close( &( pDecDummy->hDirACRend ) ); - ivas_spat_hSpatParamRendCom_close( &( pDecDummy->hSpatParamRendCom ) ); ivas_dirac_dec_close( &( pDecDummy->hDirAC ) ); /* Qmetadata handle */ @@ -3370,9 +3447,6 @@ static void freeDecoderDummy( pDecDummy->hoa_dec_mtx = NULL; } - /* Parametric binaural renderer HRTF structure */ - free( pDecDummy->hHrtfParambin ); - /* Parametric binaural renderer handle */ ivas_dirac_dec_close_binaural_data( &pDecDummy->hDiracDecBin ); @@ -3392,11 +3466,17 @@ static void clearInputMasa( rendCtx = inputMasa->base.ctx; +#ifdef REND_STATIC_MEM_OPT freeInputBaseBufferData( &inputMasa->bufferData ); +#endif masaPrerendClose( &inputMasa->hMasaPrerend ); - initRendInputBase( &inputMasa->base, IVAS_REND_AUDIO_CONFIG_UNKNOWN, 0, rendCtx, - NULL, 0 ); + initRendInputBase( &inputMasa->base, IVAS_REND_AUDIO_CONFIG_UNKNOWN, 0, rendCtx +#ifdef REND_STATIC_MEM_OPT + , + NULL, 0 +#endif + ); freeDecoderDummy( &inputMasa->decDummy ); return; @@ -3547,8 +3627,12 @@ ivas_error IVAS_REND_Open( for ( i = 0; i < RENDERER_MAX_ISM_INPUTS; ++i ) { - initRendInputBase( &hIvasRend->inputsIsm[i].base, IVAS_REND_AUDIO_CONFIG_UNKNOWN, 0, getRendCtx( hIvasRend ), - NULL, 0 ); + initRendInputBase( &hIvasRend->inputsIsm[i].base, IVAS_REND_AUDIO_CONFIG_UNKNOWN, 0, getRendCtx( hIvasRend ) +#ifdef REND_STATIC_MEM_OPT + , + NULL, 0 +#endif + ); hIvasRend->inputsIsm[i].crendWrapper = NULL; hIvasRend->inputsIsm[i].hReverb = NULL; hIvasRend->inputsIsm[i].tdRendWrapper.hBinRendererTd = NULL; @@ -3559,7 +3643,9 @@ ivas_error IVAS_REND_Open( hIvasRend->inputsIsm[i].splitTdRendWrappers[j].hHrtfTD = NULL; } #endif +#ifdef REND_STATIC_MEM_OPT hIvasRend->inputsIsm[i].bufferData = NULL; +#endif hIvasRend->inputsIsm[i].nonDiegeticPan = nonDiegeticPan; hIvasRend->inputsIsm[i].nonDiegeticPanGain = nonDiegeticPanGain; hIvasRend->inputsIsm[i].hOMasa = NULL; @@ -3567,13 +3653,19 @@ ivas_error IVAS_REND_Open( for ( i = 0; i < RENDERER_MAX_MC_INPUTS; ++i ) { - initRendInputBase( &hIvasRend->inputsMc[i].base, IVAS_REND_AUDIO_CONFIG_UNKNOWN, 0, getRendCtx( hIvasRend ), - NULL, 0 ); + initRendInputBase( &hIvasRend->inputsMc[i].base, IVAS_REND_AUDIO_CONFIG_UNKNOWN, 0, getRendCtx( hIvasRend ) +#ifdef REND_STATIC_MEM_OPT + , + NULL, 0 +#endif + ); hIvasRend->inputsMc[i].efapInWrapper.hEfap = NULL; hIvasRend->inputsMc[i].crendWrapper = NULL; hIvasRend->inputsMc[i].hReverb = NULL; hIvasRend->inputsMc[i].tdRendWrapper.hBinRendererTd = NULL; +#ifdef REND_STATIC_MEM_OPT hIvasRend->inputsMc[i].bufferData = NULL; +#endif hIvasRend->inputsMc[i].nonDiegeticPan = nonDiegeticPan; hIvasRend->inputsMc[i].nonDiegeticPanGain = nonDiegeticPanGain; hIvasRend->inputsMc[i].hMcMasa = NULL; @@ -3588,24 +3680,36 @@ ivas_error IVAS_REND_Open( for ( i = 0; i < RENDERER_MAX_SBA_INPUTS; ++i ) { - initRendInputBase( &hIvasRend->inputsSba[i].base, IVAS_REND_AUDIO_CONFIG_UNKNOWN, 0, getRendCtx( hIvasRend ), - NULL, 0 ); + initRendInputBase( &hIvasRend->inputsSba[i].base, IVAS_REND_AUDIO_CONFIG_UNKNOWN, 0, getRendCtx( hIvasRend ) +#ifdef REND_STATIC_MEM_OPT + , + NULL, 0 +#endif + ); hIvasRend->inputsSba[i].crendWrapper = NULL; #ifdef SPLIT_REND_WITH_HEAD_ROT hIvasRend->inputsSba[i].cldfbRendWrapper.hCldfbRend = NULL; hIvasRend->inputsSba[i].cldfbRendWrapper.hHrtfFastConv = NULL; #endif +#ifdef REND_STATIC_MEM_OPT hIvasRend->inputsSba[i].bufferData = NULL; +#endif hIvasRend->inputsSba[i].hDirAC = NULL; } for ( i = 0; i < RENDERER_MAX_MASA_INPUTS; ++i ) { - initRendInputBase( &hIvasRend->inputsMasa[i].base, IVAS_REND_AUDIO_CONFIG_UNKNOWN, 0, getRendCtx( hIvasRend ), - NULL, 0 ); + initRendInputBase( &hIvasRend->inputsMasa[i].base, IVAS_REND_AUDIO_CONFIG_UNKNOWN, 0, getRendCtx( hIvasRend ) +#ifdef REND_STATIC_MEM_OPT + , + NULL, 0 +#endif + ); hIvasRend->inputsMasa[i].decDummy = NULL; hIvasRend->inputsMasa[i].metadataHasBeenFed = false; +#ifdef REND_STATIC_MEM_OPT hIvasRend->inputsMasa[i].bufferData = NULL; +#endif hIvasRend->inputsMasa[i].hMasaPrerend = NULL; } #ifdef SPLIT_REND_WITH_HEAD_ROT @@ -3614,13 +3718,20 @@ ivas_error IVAS_REND_Open( initRendInputBase( &hIvasRend->inputsSplitPost[i].base, IVAS_REND_AUDIO_CONFIG_UNKNOWN, 0, - getRendCtx( hIvasRend ), - NULL, 0 ); + getRendCtx( hIvasRend ) +#ifdef REND_STATIC_MEM_OPT + , + NULL, 0 +#endif + ); ivas_init_split_post_rend_handles( &hIvasRend->inputsSplitPost[i].splitPostRendWrapper ); #ifdef SPLIT_REND_WITH_HEAD_ROT hIvasRend->splitRendBFI = 0; #endif +#ifdef REND_STATIC_MEM_OPT hIvasRend->inputsSplitPost[i].bufferData = NULL; + +#endif } #endif @@ -4982,7 +5093,11 @@ ivas_error IVAS_REND_SetHeadRotation( ( hIvasRend->inputsSplitPost[0].base.inConfig == IVAS_REND_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || ( hIvasRend->inputsSplitPost[0].base.inConfig == IVAS_REND_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) { +#ifndef EULER2QUAT_FIX + rotQuat = headRot[i]; /* TODO: temp change until Euler2Quat() is fixed*/ +#else Euler2Quat( deg2rad( headRot[i].x ), deg2rad( headRot[i].y ), deg2rad( headRot[i].z ), &rotQuat ); +#endif } else #endif @@ -5471,13 +5586,19 @@ static ivas_error rotateFrameSba( int16_t m1, m2; int16_t shd_rot_max_order; int16_t subframe_idx, subframe_len; +#ifdef SBA_CREND_ROT_OPT float *writePtr; +#else + float *readPtr, *writePtr; +#endif rotation_matrix Rmat; float tmpRot[2 * HEADROT_ORDER + 1]; rotation_gains gains; ivas_error error; +#ifdef SBA_CREND_ROT_OPT int16_t idx; float val, cf, oneminuscf; +#endif push_wmops( "rotateFrameSba" ); @@ -5518,9 +5639,11 @@ static ivas_error rotateFrameSba( for ( i = 0; i < subframe_len; i++ ) { +#ifdef SBA_CREND_ROT_OPT idx = subframe_idx * subframe_len + i; cf = headRotData->crossfade[i]; oneminuscf = 1 - cf; +#endif /* As the rotation matrix becomes block diagonal in a SH basis, we can*/ /* apply each angular-momentum block individually to save complexity. */ @@ -5536,9 +5659,16 @@ static ivas_error rotateFrameSba( for ( m = m1; m < m2; m++ ) { +#ifdef SBA_CREND_ROT_OPT val = inAudio.data[m * inAudio.config.numSamplesPerChannel + idx]; /* crossfade with previous rotation gains */ tmpRot[n - m1] += ( cf * gains[n][m] * val + oneminuscf * gains_prev[n][m] * val ); +#else + readPtr = getSmplPtr( inAudio, m, subframe_idx * subframe_len + i ); + /* crossfade with previous rotation gains */ + tmpRot[n - m1] += headRotData->crossfade[i] * gains[n][m] * ( *readPtr ) + + ( 1 - headRotData->crossfade[i] ) * gains_prev[n][m] * ( *readPtr ); +#endif } } /* write back the result */ @@ -5754,7 +5884,6 @@ static ivas_error renderIsmToBinauralRoom( return IVAS_ERR_OK; } - static ivas_error renderIsmToBinauralReverb( input_ism *ismInput, IVAS_REND_AudioBuffer outAudio ) @@ -7692,41 +7821,44 @@ static ivas_error renderActiveInputsSba( static void copyMasaMetadataToDiracRenderer( MASA_METADATA_FRAME *meta, - SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom ) + DIRAC_DEC_HANDLE hDirAC ) { int16_t band, sf, bin; int16_t meta_write_index; - hSpatParamRendCom->numSimultaneousDirections = meta->descriptive_meta.numberOfDirections + 1; +#ifdef MASA_AND_OBJECTS + hDirAC->numParametricDirections = meta->descriptive_meta.numberOfDirections + 1; +#endif + hDirAC->numSimultaneousDirections = meta->descriptive_meta.numberOfDirections + 1; for ( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ ) { - meta_write_index = ( hSpatParamRendCom->dirac_bs_md_write_idx + sf ) % hSpatParamRendCom->dirac_md_buffer_length; + meta_write_index = ( hDirAC->dirac_bs_md_write_idx + sf ) % hDirAC->dirac_md_buffer_length; for ( band = 0; band < MASA_MAXIMUM_CODING_SUBBANDS; band++ ) { for ( bin = MASA_band_grouping_24[band]; bin < MASA_band_grouping_24[band + 1]; bin++ ) { - hSpatParamRendCom->azimuth[meta_write_index][bin] = (int16_t) meta->directional_meta[0].azimuth[sf][band]; - hSpatParamRendCom->elevation[meta_write_index][bin] = (int16_t) meta->directional_meta[0].elevation[sf][band]; - hSpatParamRendCom->energy_ratio1[meta_write_index][bin] = meta->directional_meta[0].energy_ratio[sf][band]; - hSpatParamRendCom->diffuseness_vector[meta_write_index][bin] = 1.0f - meta->directional_meta[0].energy_ratio[sf][band]; - hSpatParamRendCom->spreadCoherence[meta_write_index][bin] = meta->directional_meta[0].spread_coherence[sf][band]; - hSpatParamRendCom->surroundingCoherence[meta_write_index][bin] = meta->common_meta.surround_coherence[sf][band]; - - if ( hSpatParamRendCom->numSimultaneousDirections == 2 ) + hDirAC->azimuth[meta_write_index][bin] = (int16_t) meta->directional_meta[0].azimuth[sf][band]; + hDirAC->elevation[meta_write_index][bin] = (int16_t) meta->directional_meta[0].elevation[sf][band]; + hDirAC->energy_ratio1[meta_write_index][bin] = meta->directional_meta[0].energy_ratio[sf][band]; + hDirAC->diffuseness_vector[meta_write_index][bin] = 1.0f - meta->directional_meta[0].energy_ratio[sf][band]; + hDirAC->spreadCoherence[meta_write_index][bin] = meta->directional_meta[0].spread_coherence[sf][band]; + hDirAC->surroundingCoherence[meta_write_index][bin] = meta->common_meta.surround_coherence[sf][band]; + + if ( hDirAC->numSimultaneousDirections == 2 ) { - hSpatParamRendCom->azimuth2[meta_write_index][bin] = (int16_t) meta->directional_meta[1].azimuth[sf][band]; - hSpatParamRendCom->elevation2[meta_write_index][bin] = (int16_t) meta->directional_meta[1].elevation[sf][band]; - hSpatParamRendCom->energy_ratio2[meta_write_index][bin] = meta->directional_meta[1].energy_ratio[sf][band]; - hSpatParamRendCom->diffuseness_vector[meta_write_index][bin] -= meta->directional_meta[1].energy_ratio[sf][band]; - hSpatParamRendCom->spreadCoherence2[meta_write_index][bin] = meta->directional_meta[1].spread_coherence[sf][band]; + hDirAC->azimuth2[meta_write_index][bin] = (int16_t) meta->directional_meta[1].azimuth[sf][band]; + hDirAC->elevation2[meta_write_index][bin] = (int16_t) meta->directional_meta[1].elevation[sf][band]; + hDirAC->energy_ratio2[meta_write_index][bin] = meta->directional_meta[1].energy_ratio[sf][band]; + hDirAC->diffuseness_vector[meta_write_index][bin] -= meta->directional_meta[1].energy_ratio[sf][band]; + hDirAC->spreadCoherence2[meta_write_index][bin] = meta->directional_meta[1].spread_coherence[sf][band]; } } } } - hSpatParamRendCom->dirac_bs_md_write_idx = ( hSpatParamRendCom->dirac_bs_md_write_idx + MAX_PARAM_SPATIAL_SUBFRAMES ) % hSpatParamRendCom->dirac_md_buffer_length; + hDirAC->dirac_bs_md_write_idx = ( hDirAC->dirac_bs_md_write_idx + MAX_PARAM_SPATIAL_SUBFRAMES ) % hDirAC->dirac_md_buffer_length; return; } @@ -7738,7 +7870,7 @@ static void renderMasaToMc( float tmpBuffer[MAX_OUTPUT_CHANNELS][L_FRAME48k]; copyBufferTo2dArray( masaInput->base.inputBuffer, tmpBuffer ); - copyMasaMetadataToDiracRenderer( &masaInput->masaMetadata, masaInput->decDummy->hSpatParamRendCom ); + copyMasaMetadataToDiracRenderer( &masaInput->masaMetadata, masaInput->decDummy->hDirAC ); if ( masaInput->decDummy->renderer_type == RENDERER_STEREO_PARAMETRIC ) { @@ -7761,7 +7893,7 @@ static void renderMasaToSba( float tmpBuffer[MAX_OUTPUT_CHANNELS][L_FRAME48k]; copyBufferTo2dArray( masaInput->base.inputBuffer, tmpBuffer ); - copyMasaMetadataToDiracRenderer( &masaInput->masaMetadata, masaInput->decDummy->hSpatParamRendCom ); + copyMasaMetadataToDiracRenderer( &masaInput->masaMetadata, masaInput->decDummy->hDirAC ); ivas_dirac_dec( masaInput->decDummy, tmpBuffer, masaInput->base.inputBuffer.config.numChannels ); @@ -7777,7 +7909,7 @@ static void renderMasaToBinaural( float tmpBuffer[MAX_OUTPUT_CHANNELS][L_FRAME48k]; copyBufferTo2dArray( masaInput->base.inputBuffer, tmpBuffer ); - copyMasaMetadataToDiracRenderer( &masaInput->masaMetadata, masaInput->decDummy->hSpatParamRendCom ); + copyMasaMetadataToDiracRenderer( &masaInput->masaMetadata, masaInput->decDummy->hDirAC ); ivas_dirac_dec_binaural( masaInput->decDummy, *masaInput->base.ctx.pCombinedOrientationData, tmpBuffer, masaInput->base.inputBuffer.config.numChannels ); diff --git a/scripts/config/self_test.prm b/scripts/config/self_test.prm index f0b30c28cf9395f3df439267b6f33d4d69905baa..a4e3fd041f833e25084ed69b4973f0742ed42d72 100644 --- a/scripts/config/self_test.prm +++ b/scripts/config/self_test.prm @@ -754,22 +754,6 @@ ../IVAS_cod -sba 3 ../scripts/switchPaths/sw_13k2_512k.bin 48 testv/stv3OA48c.wav bit ../IVAS_dec HOA3 48 bit testv/stv3OA48c.wav_sw_48-48_HOA3.tst -// SBA 3OA bitrate switching from 13.2 kbps to 512 kbps, 48kHz in, 48kHz out, MONO out -../IVAS_cod -sba 3 ../scripts/switchPaths/sw_13k2_512k.bin 48 testv/stv3OA48c.wav bit -../IVAS_dec MONO 48 bit testv/stv3OA48c.wav_sw_48-48_MONO.tst - -// SBA 3OA bitrate switching from 13.2 kbps to 512 kbps, 48kHz in, 48kHz out, STEREO out -../IVAS_cod -sba 3 ../scripts/switchPaths/sw_13k2_512k.bin 48 testv/stv3OA48c.wav bit -../IVAS_dec STEREO 48 bit testv/stv3OA48c.wav_sw_48-48_STEREO.tst - -// SBA 3OA bitrate switching from 13.2 kbps to 512 kbps, 48kHz in, 48kHz out, BINAURAL out -../IVAS_cod -sba 3 ../scripts/switchPaths/sw_13k2_512k.bin 48 testv/stv3OA48c.wav bit -../IVAS_dec BINAURAL 48 bit testv/stv3OA48c.wav_sw_48-48_BINAURAL.tst - -// SBA 3OA bitrate switching from 13.2 kbps to 512 kbps, 48kHz in, 48kHz out, FOA out -../IVAS_cod -sba 3 ../scripts/switchPaths/sw_13k2_512k.bin 48 testv/stv3OA48c.wav bit -../IVAS_dec FOA 48 bit testv/stv3OA48c.wav_sw_48-48_FOA.tst - // SBA planar 3OA bitrate switching from 24.4 kbps to 256 kbps, 48kHz in, 48kHz out, 7_1_4 out ../IVAS_cod -sba -3 ../scripts/switchPaths/sw_24k4_256k.bin 48 testv/stv3OA48c.wav bit ../IVAS_dec 7_1_4 48 bit testv/stv3OA48c.wav_sw_48-48_7_1_4.tst @@ -944,43 +928,10 @@ ../IVAS_cod -masa 1 testv/stv1MASA1TC48n.met ../scripts/switchPaths/sw_13k2_to_128k_10fr.bin 48 testv/stv1MASA1TC48n.wav bit ../IVAS_dec 5_1 48 bit testv/stv1MASA1TC48n.wav_sw_48-48_5_1.tst -// MASA 1dir 1TC bitrate switching from 13.2 kbps to 128 kbps, 48kHz in, 48kHz out, STEREO out -../IVAS_cod -masa 1 testv/stv1MASA1TC48n.met ../scripts/switchPaths/sw_13k2_to_128k_10fr.bin 48 testv/stv1MASA1TC48n.wav bit -../IVAS_dec STEREO 48 bit testv/stv1MASA1TC48n.wav_sw_48-48_STEREO.tst - -// MASA 1dir 1TC bitrate switching from 13.2 kbps to 128 kbps, 48kHz in, 48kHz out, BINAURAL out -../IVAS_cod -masa 1 testv/stv1MASA1TC48n.met ../scripts/switchPaths/sw_13k2_to_128k_10fr.bin 48 testv/stv1MASA1TC48n.wav bit -../IVAS_dec BINAURAL 48 bit testv/stv1MASA1TC48n.wav_sw_48-48_BINAURAL.tst - -// MASA 1dir 1TC bitrate switching from 13.2 kbps to 128 kbps, 48kHz in, 48kHz out, FOA out -../IVAS_cod -masa 1 testv/stv1MASA1TC48n.met ../scripts/switchPaths/sw_13k2_to_128k_10fr.bin 48 testv/stv1MASA1TC48n.wav bit -../IVAS_dec FOA 48 bit testv/stv1MASA1TC48n.wav_sw_48-48_FOA.tst - // MASA 1dir 2TC bitrate switching from 13.2 kbps to 512 kbps, 48kHz in, 48kHz out, BINAURAL out ../IVAS_cod -masa 2 testv/stv1MASA2TC48n.met ../scripts/switchPaths/sw_13k2_512k.bin 48 testv/stv1MASA2TC48n.wav bit ../IVAS_dec BINAURAL 48 bit testv/stv1MASA2TC48n.wav_sw_48-48_BINAURAL.tst -// MASA 1dir 2TC bitrate switching from 13.2 kbps to 512 kbps, 48kHz in, 48kHz out, MONO out -../IVAS_cod -masa 2 testv/stv1MASA2TC48n.met ../scripts/switchPaths/sw_13k2_512k.bin 48 testv/stv1MASA2TC48n.wav bit -../IVAS_dec MONO 48 bit testv/stv1MASA2TC48n.wav_sw_48-48_MONO.tst - -// MASA 1dir 2TC bitrate switching from 13.2 kbps to 512 kbps, 48kHz in, 48kHz out, 7_1 out -../IVAS_cod -masa 2 testv/stv1MASA2TC48n.met ../scripts/switchPaths/sw_13k2_512k.bin 48 testv/stv1MASA2TC48n.wav bit -../IVAS_dec 7_1 48 bit testv/stv1MASA2TC48n.wav_sw_48-48_7_1.tst - -// MASA 1dir 2TC bitrate switching from 13.2 kbps to 512 kbps, 48kHz in, 48kHz out, MONO out -../IVAS_cod -masa 2 testv/stv1MASA2TC48n.met ../scripts/switchPaths/sw_13k2_512k.bin 48 testv/stv1MASA2TC48n.wav bit -../IVAS_dec MONO 48 bit testv/stv1MASA2TC48n.wav_sw_48-48_MONO.tst - -// MASA 2dir 2TC bitrate switching from 13.2 kbps to 512 kbps, 48kHz in, 48kHz out, 7_1 out -../IVAS_cod -masa 2 testv/stv2MASA2TC48c.met ../scripts/switchPaths/sw_13k2_512k.bin 48 testv/stv2MASA2TC48c.wav bit -../IVAS_dec 7_1 48 bit testv/stv2MASA2TC48c.wav_sw_48-48_7_1.tst - -// MASA 2dir 2TC bitrate switching from 13.2 kbps to 512 kbps, 48kHz in, 48kHz out, BINAURAL out -../IVAS_cod -masa 2 testv/stv2MASA2TC48c.met ../scripts/switchPaths/sw_13k2_512k.bin 48 testv/stv2MASA2TC48c.wav bit -../IVAS_dec BINAURAL 48 bit testv/stv2MASA2TC48c.wav_sw_48-48_BINAURAL.tst - - // Multi-channel 5_1 at 13.2 kbps, 48kHz in, 48kHz out @@ -1187,10 +1138,6 @@ ../IVAS_cod -mc 7_1_4 ../scripts/switchPaths/sw_24k4_256k.bin 48 testv/stv714MC48c.wav bit ../IVAS_dec -FEC 5 STEREO 32 bit testv/stv714MC48c.wav_sw_48-32_stereo.tst -// Multi-channel 7_1_4 bitrate switching from 13.2 kbps to 512 kbps, 48kHz in, 48kHz out, BINAURAL out -../IVAS_cod -mc 7_1_4 ../scripts/switchPaths/sw_mctech_5fr.bin 48 testv/stv714MC48c.wav bit -../IVAS_dec BINAURAL 48 bit testv/stv51MC48c.wav_sw_48-48_BINAURAL.tst - // Multi-channel 5_1_4 at 512 kbps, 48kHz in, 16kHz out, BINAURAL_ROOM out (Model from file) ../IVAS_cod -mc 5_1_4 512000 48 testv/stv514MC48c.wav bit diff --git a/tests/codec_be_on_mr_selection/__init__.py b/tests/codec_be_on_mr_selection/__init__.py index b7f4cd8efeffaff30d451bb9d0eb49945f68a47d..34a307a7393396bbb6aa614f4d496e25c2757bc2 100644 --- a/tests/codec_be_on_mr_selection/__init__.py +++ b/tests/codec_be_on_mr_selection/__init__.py @@ -35,7 +35,6 @@ import filecmp from pathlib import Path import subprocess from .constants import OUTPUT_MODES_AND_OPTIONS_FOR_EXPERIMENT, DTX_ON, FER_5PERC -from ..testconfig import MD5_REF_DICT HERE = Path(__file__).parent # set environment variables in CI job @@ -99,20 +98,8 @@ def apply_error_pattern_on_bitstream( subprocess.run(cmd) -def is_be_to_ref(dut_file): - """ - Check bitexactness either by comparing files directly or by comparing MD5 sums - """ - if MD5_REF_DICT == dict(): - ref_file = REF_PATH.joinpath(dut_file.name) - is_be = filecmp.cmp(dut_file, ref_file) - else: - md5_ref = MD5_REF_DICT[dut_file.name] - cmd = f"powershell.exe (Get-FileHash {str(dut_file)} -Algorithm MD5).Hash" - md5_dut = subprocess.check_output(cmd, shell=True).decode().splitlines()[-1] - is_be = md5_ref == md5_dut - - return is_be +def files_equal(dut_file, ref_file): + return filecmp.cmp(dut_file, ref_file) def run_check( @@ -126,7 +113,6 @@ def run_check( decoder_frontend, is_ref_creation, input_file_num=None, - keep_files=True, ): sampling_rate = 48 output_mode, options = OUTPUT_MODES_AND_OPTIONS_FOR_EXPERIMENT[experiment] @@ -161,8 +147,9 @@ def run_check( add_option_list=options + [str(f) for f in metadata], ) - if not is_be_to_ref(dut_bitstream): - pytest.fail(f"Bitstream file differs from reference") + ref_bitstream = REF_PATH.joinpath(dut_bitstream.name) + if not is_ref_creation and not files_equal(dut_bitstream, ref_bitstream): + pytest.fail("Bitstream file differs from reference") dut_bitstream_to_decoder = dut_bitstream if error_pattern is not None: @@ -181,15 +168,12 @@ def run_check( # this should not be a problem as both the reference and the tdut output was generated by the codec, so # diverging headers should also indicate a problem - still, keep in mind if something bogus happens if not is_ref_creation: - if not is_be_to_ref(dut_output): + ref_output = REF_PATH.joinpath(dut_output.name) + if not files_equal(dut_output, ref_output): pytest.fail("Decoder output differs from reference") - elif not keep_files: - os.remove(dut_output) - os.remove(dut_bitstream) for md in metadata: md_suffix = "".join(md.suffixes) dut_md = DUT_PATH.joinpath(dut_output.with_suffix(md_suffix).name) - if not is_be_to_ref(dut_md): + ref_md = REF_PATH.joinpath(dut_output.with_suffix(md_suffix).name) + if not files_equal(dut_md, ref_md): pytest.fail("Metadata file {md.name} differs from reference") - elif not keep_files: - os.remove(dut_md) diff --git a/tests/codec_be_on_mr_selection/test_experiments.py b/tests/codec_be_on_mr_selection/test_experiments.py index 5b2f51689342117c2e543442a974bce6714ff6fc..a0a4aa780a757cf887e6b80e72a8a48eed00899d 100644 --- a/tests/codec_be_on_mr_selection/test_experiments.py +++ b/tests/codec_be_on_mr_selection/test_experiments.py @@ -52,7 +52,6 @@ def test_p800( dut_encoder_frontend, dut_decoder_frontend, update_ref, - keep_files, ): run_check( experiment, @@ -64,7 +63,6 @@ def test_p800( dut_encoder_frontend, dut_decoder_frontend, update_ref == 1, - keep_files=keep_files, ) @@ -81,7 +79,6 @@ def test_bs1534_no_masa( dut_encoder_frontend, dut_decoder_frontend, update_ref, - keep_files, ): category = "" run_check( @@ -95,7 +92,6 @@ def test_bs1534_no_masa( dut_decoder_frontend, update_ref == 1, input_file_num=input_file_num, - keep_files=keep_files, ) @@ -115,7 +111,6 @@ def test_bs1534_masa( dut_encoder_frontend, dut_decoder_frontend, update_ref, - keep_files, ): run_check( experiment, @@ -128,5 +123,4 @@ def test_bs1534_masa( dut_decoder_frontend, update_ref == 1, input_file_num=input_file_num, - keep_files=keep_files, ) diff --git a/tests/conftest.py b/tests/conftest.py index e4de453b0ea6698f9600076ded65a53a1a2b7d51..12b62caccd9d49cd003b204cfe8ce7e307674a24 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -133,12 +133,6 @@ def pytest_addoption(parser): " Use --keep_files to prevent these deletions.", ) - parser.addoption( - "--selection_be_md5_file", - type=Path, - help="Path to file with md5 sums for the reference signals of the selection-BE test" - ) - @pytest.fixture(scope="session", autouse=True) def update_ref(request): @@ -519,9 +513,3 @@ def pytest_configure(config): ) if config.option.param_file: testconfig.PARAM_FILE = config.option.param_file - if config.option.selection_be_md5_file: - md5_file_path = config.option.selection_be_md5_file - if not platform.system() == "Windows": - raise NotImplementedError("MD5 comparison is currently hardcoded for windows") - with open(md5_file_path) as f: - testconfig.MD5_REF_DICT = {line.split()[0]: line.split()[1] for line in f.readlines()} diff --git a/tests/testconfig.py b/tests/testconfig.py index 1dbfbb840343801460f1548b4e8b662d9ce96e6e..12d170ba8db49171e16add1f827a590ffcb09bd3 100644 --- a/tests/testconfig.py +++ b/tests/testconfig.py @@ -35,5 +35,3 @@ To configure test modules. """ PARAM_FILE = "scripts/config/self_test.prm" - -MD5_REF_DICT = dict() \ No newline at end of file