diff --git a/CMakeLists.txt b/CMakeLists.txt index bae6fa624ebf843f67e5bad98d09961d4465519c..7beb46c45129b2cae7d076830f99cae494e417ea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -192,6 +192,12 @@ if(WIN32) target_link_libraries(IVAS_cod Ws2_32) endif() +add_executable(IVAS_cod_fmtsw apps/encoder_fmtsw.c) +target_link_libraries(IVAS_cod_fmtsw lib_enc lib_util) +if(WIN32) + target_link_libraries(IVAS_cod_fmtsw Ws2_32) +endif() + add_executable(IVAS_dec apps/decoder.c) target_link_libraries(IVAS_dec lib_dec lib_util) if(WIN32) @@ -216,6 +222,7 @@ target_include_directories(ambi_converter PRIVATE lib_util) if(COPY_EXECUTABLES_FROM_BUILD_DIR) # Optionally copy executables to the same place where Make puts them (useful for tests that expect executables in specific places) add_custom_command(TARGET IVAS_cod POST_BUILD VERBATIM COMMAND "${CMAKE_COMMAND}" -E copy "$" "${CMAKE_CURRENT_SOURCE_DIR}/") + add_custom_command(TARGET IVAS_cod_fmtsw POST_BUILD VERBATIM COMMAND "${CMAKE_COMMAND}" -E copy "$" "${CMAKE_CURRENT_SOURCE_DIR}/") add_custom_command(TARGET IVAS_dec POST_BUILD VERBATIM COMMAND "${CMAKE_COMMAND}" -E copy "$" "${CMAKE_CURRENT_SOURCE_DIR}/") add_custom_command(TARGET IVAS_rend POST_BUILD VERBATIM COMMAND "${CMAKE_COMMAND}" -E copy "$" "${CMAKE_CURRENT_SOURCE_DIR}/") add_custom_command(TARGET ISAR_post_rend POST_BUILD VERBATIM COMMAND "${CMAKE_COMMAND}" -E copy "$" "${CMAKE_CURRENT_SOURCE_DIR}/") diff --git a/Makefile b/Makefile index b2a42917c44210b4e25734c2779afa4077ceaecc..b2b5979898ada5e92d1da23d62974ef06b5aae48 100644 --- a/Makefile +++ b/Makefile @@ -18,6 +18,7 @@ SRC_DIRS = $(sort -u $(SRC_LIBCOM) $(SRC_LIBDEBUG) $(SRC_LIBDEC) $(SRC_LIBENC) # Name of CLI binaries CLI_APIDEC ?= IVAS_dec CLI_APIENC ?= IVAS_cod +CLI_APIENC_FMTSW ?= IVAS_cod_fmtsw CLI_APIREND ?= IVAS_rend CLI_APIPOSTREND ?= ISAR_post_rend CLI_AMBICONVERT ?= ambi_converter @@ -157,6 +158,7 @@ OBJS_LIBUTIL = $(addprefix $(OBJDIR)/,$(SRCS_LIBUTIL:.c=.o)) OBJS_AMBICONVERT = $(OBJDIR)/ambi_convert.o OBJS_CLI_APIDEC = $(OBJDIR)/decoder.o OBJS_CLI_APIENC = $(OBJDIR)/encoder.o +OBJS_CLI_APIENC_FMTSW = $(OBJDIR)/encoder_fmtsw.o OBJS_CLI_APPREND = $(OBJDIR)/renderer.o OBJS_CLI_APPPOSTREND = $(OBJDIR)/isar_post_rend.o OBJS_CLI_AMBICONVERT = $(OBJDIR)/ambi_converter.o @@ -169,7 +171,7 @@ DEPS = $(addprefix $(OBJDIR)/,$(SRCS_LIBCOM:.c=.P) $(SRCS_LIBDEBUG:.c=.P) $(SRCS .PHONY: all clean -all: $(CLI_APIENC) $(CLI_APIDEC) $(CLI_APIREND) $(CLI_APIPOSTREND) $(CLI_AMBICONVERT) +all: $(CLI_APIENC) $(CLI_APIENC_FMTSW) $(CLI_APIDEC) $(CLI_APIREND) $(CLI_APIPOSTREND) $(CLI_AMBICONVERT) $(OBJDIR): $(QUIET)mkdir -p $(OBJDIR) @@ -201,6 +203,9 @@ $(LIB_LIBUTIL): $(OBJS_LIBUTIL) $(CLI_APIENC): $(OBJS_CLI_APIENC) $(LIB_LIBENC) $(LIB_LIBCOM) $(LIB_LIBUTIL) $(LIB_LIBDEBUG) $(LIB_LC3PLUS) $(QUIET_LINK)$(CC) $(LDFLAGS) $(OBJS_CLI_APIENC) -L. -livasenc -livascom -livasutil -livasdebug $(LDLIBS) -o $(CLI_APIENC) +$(CLI_APIENC_FMTSW): $(OBJS_CLI_APIENC_FMTSW) $(LIB_LIBENC) $(LIB_LIBCOM) $(LIB_LIBUTIL) $(LIB_LIBDEBUG) $(LIB_LC3PLUS) + $(QUIET_LINK)$(CC) $(LDFLAGS) $(OBJS_CLI_APIENC_FMTSW) -L. -livasenc -livascom -livasutil -livasdebug $(LDLIBS) -o $(CLI_APIENC_FMTSW) + $(CLI_APIDEC): $(OBJS_CLI_APIDEC) $(LIB_LIBDEC) $(LIB_LIBCOM) $(LIB_LIBUTIL) $(LIB_LIBDEBUG) $(LIB_LC3PLUS) $(LIB_LIBISAR) $(QUIET_LINK)$(CC) $(LDFLAGS) $(OBJS_CLI_APIDEC) -L. -livasdec -livascom -livasutil -livasdebug -llc3plus $(LDLIBS) -o $(CLI_APIDEC) @@ -219,7 +224,7 @@ clean: $(QUIET)$(RM) $(OBJS_LIBENC) $(OBJS_LIBDEC) $(DEPS) $(QUIET)$(RM) $(DEPS:.P=.d) $(QUIET)test ! -d $(OBJDIR) || rm -rf $(OBJDIR) - $(QUIET)$(RM) $(CLI_APIENC) $(CLI_APIDEC) $(CLI_APIREND) $(CLI_APIPOSTREND) $(CLI_AMBICONVERT) $(LIB_LIBENC) $(LIB_LIBDEBUG) $(LIB_LIBCOM) $(LIB_LIBDEC) $(LIB_LIBUTIL) $(LIB_LIBREND) $(LIB_LIBISAR) $(LIB_LC3PLUS) + $(QUIET)$(RM) $(CLI_APIENC) $(CLI_APIENC_FMTSW) $(CLI_APIDEC) $(CLI_APIREND) $(CLI_APIPOSTREND) $(CLI_AMBICONVERT) $(LIB_LIBENC) $(LIB_LIBDEBUG) $(LIB_LIBCOM) $(LIB_LIBDEC) $(LIB_LIBUTIL) $(LIB_LIBREND) $(LIB_LIBISAR) $(LIB_LC3PLUS) $(OBJDIR)/%.o : %.c | $(OBJDIR) $(QUIET_CC)$(CC) $(CFLAGS) -c -MD -o $@ $< diff --git a/Workspace_msvc/Workspace_msvc.sln b/Workspace_msvc/Workspace_msvc.sln index 6a38a0e4304fea3680886ea0b2080bfd04630b34..b87f6c936635bc81342decbd647f7d9ca000c8ec 100644 --- a/Workspace_msvc/Workspace_msvc.sln +++ b/Workspace_msvc/Workspace_msvc.sln @@ -18,6 +18,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "decoder", "decoder.vcxproj" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "encoder", "encoder.vcxproj", "{B3FC9DFC-7268-8660-7C0D-B60BAF02C554}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "encoder_fmtsw", "encoder_fmtsw.vcxproj", "{CA7EA15E-09A4-4196-A8EA-2A5F6F84862B}" +EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "renderer", "renderer.vcxproj", "{12B4C8A5-1E06-4E30-B443-D1F916F52B47}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lib_lc3plus", "lib_lc3plus.vcxproj", "{95030B82-70CD-4C6B-84D4-61096035BEA2}" @@ -89,6 +91,12 @@ Global {B3FC9DFC-7268-8660-7C0D-B60BAF02C554}.Release|Win32.ActiveCfg = Release|Win32 {B3FC9DFC-7268-8660-7C0D-B60BAF02C554}.Release|Win32.Build.0 = Release|Win32 {B3FC9DFC-7268-8660-7C0D-B60BAF02C554}.Release|x64.ActiveCfg = Release|Win32 + {CA7EA15E-09A4-4196-A8EA-2A5F6F84862B}.Debug|Win32.ActiveCfg = Debug|Win32 + {CA7EA15E-09A4-4196-A8EA-2A5F6F84862B}.Debug|Win32.Build.0 = Debug|Win32 + {CA7EA15E-09A4-4196-A8EA-2A5F6F84862B}.Debug|x64.ActiveCfg = Debug|Win32 + {CA7EA15E-09A4-4196-A8EA-2A5F6F84862B}.Release|Win32.ActiveCfg = Release|Win32 + {CA7EA15E-09A4-4196-A8EA-2A5F6F84862B}.Release|Win32.Build.0 = Release|Win32 + {CA7EA15E-09A4-4196-A8EA-2A5F6F84862B}.Release|x64.ActiveCfg = Release|Win32 {12B4C8A5-1E06-4E30-B443-D1F916F52B47}.Debug|Win32.ActiveCfg = Debug|Win32 {12B4C8A5-1E06-4E30-B443-D1F916F52B47}.Debug|Win32.Build.0 = Debug|Win32 {12B4C8A5-1E06-4E30-B443-D1F916F52B47}.Debug|x64.ActiveCfg = Debug|Win32 diff --git a/Workspace_msvc/encoder_fmtsw.vcxproj b/Workspace_msvc/encoder_fmtsw.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..c3a81b18f366001d4c8f6e4467230ea6ccd47400 --- /dev/null +++ b/Workspace_msvc/encoder_fmtsw.vcxproj @@ -0,0 +1,180 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + encoder_fmtsw + {CA7EA15E-09A4-4196-A8EA-2A5F6F84862B} + encoder_fmtsw + 10.0.17763.0 + + + + Application + v141 + false + MultiByte + + + Application + v141 + false + MultiByte + + + + + + + + + + + + + + + <_ProjectFileVersion>15.0.27428.2015 + + + ..\ + .\Debug_$(ProjectName)\ + false + false + IVAS_cod_fmtsw + + + ..\ + .\Release_$(ProjectName)\ + false + false + IVAS_cod_fmtsw + + + + + + + $(IntDir)$(ProjectName).tlb + + + + Disabled + ..\lib_enc;..\lib_com;..\lib_util;..\lib_debug;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;WIN32;$(Macros);%(PreprocessorDefinitions) + + EnableFastChecks + MultiThreadedDebug + false + + + $(IntDir)$(ProjectName).pdb + Level4 + true + OldStyle + Default + %(DisableSpecificWarnings) + false + + + _DEBUG;%(PreprocessorDefinitions) + 0x0c0c + + + + $(OutDir)$(TargetName).exe + true + + false + true + $(IntDir)$(ProjectName).pdb + Console + + false + + MachineX86 + + + + + + + + + + + $(IntDir)$(ProjectName).tlb + + + + MaxSpeed + AnySuitable + false + Neither + false + false + ..\lib_enc;..\lib_com;..\lib_util;..\lib_debug;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;$(Macros);%(PreprocessorDefinitions) + true + + Default + MultiThreaded + true + Precise + false + + + $(IntDir)$(ProjectName).pdb + Level4 + true + + Default + %(DisableSpecificWarnings) + false + + + NDEBUG;%(PreprocessorDefinitions) + 0x0c0c + + + $(OutDir)$(TargetName).exe + true + + false + $(IntDir)$(ProjectName).pdb + Console + false + + MachineX86 + + + + + + + + {824da4cf-06f0-45c9-929a-8792f0e19c3e} + false + + + {2fa8f384-0775-f3b7-f8c3-85209222fc70} + false + + + + + + + + + + + \ No newline at end of file diff --git a/apps/decoder.c b/apps/decoder.c index 6f7b929cd2eccb2451bb5b6146cfcd531a8a14ba..9b200437860261752c15aebf2de04a26be3f9bb8 100644 --- a/apps/decoder.c +++ b/apps/decoder.c @@ -63,9 +63,6 @@ #include "flp_debug.h" #endif -#ifdef FIXED_RTP_SEQUENCE_NUM -#define RANDOM_INITSEED_DEC ( 0xFEEDFADE ) -#endif #define WMC_TOOL_SKIP @@ -81,8 +78,15 @@ static #ifdef DEBUGGING #define MIN_NUM_BITS_ACTIVE_FRAME 56 #define NUM_BITS_SID_IVAS_5K2 104 -#endif +#endif +#ifdef NONBE_FIX_BASOP_2233_RTPDUMP_DIFFERING_BITSTREAMS +#define RANDOM_INITSEED_DEC ( 0xFADE ) +#else +#ifdef FIXED_RTP_SEQUENCE_NUM +#define RANDOM_INITSEED_DEC ( 0xFEEDFADE ) +#endif +#endif /*------------------------------------------------------------------------------------------* * Local structure for storing cmdln arguments @@ -155,6 +159,12 @@ typedef struct uint16_t directivityPatternId[IVAS_MAX_NUM_OBJECTS]; bool objEditEnabled; char *objEditFileName; +#ifdef FIX_1419_MONO_STEREO_UMX + bool evsMode; +#endif +#ifdef FIX_1318_ROOM_SIZE_CMD_LINE + IVAS_ROOM_SIZE_T roomSize; +#endif } DecArguments; @@ -183,18 +193,49 @@ typedef struct static bool parseCmdlIVAS_dec( int16_t argc, char **argv, DecArguments *arg ); static void usage_dec( void ); -static ivas_error decodeG192( DecArguments arg, BS_READER_HANDLE hBsReader, IVAS_DEC_HRTF_BINARY_WRAPPER *hHrtf, RotFileReader *headRotReader, RotFileReader *externalOrientationFileReader, RotFileReader *refRotReader, Vector3PairFileReader *referenceVectorReader, ObjectEditFileReader *objectEditFileReader, ISAR_SPLIT_REND_BITS_DATA *splitRendBits, IVAS_DEC_HANDLE hIvasDec, int16_t *pcmBuf ); +static ivas_error decodeG192( + DecArguments arg, + BS_READER_HANDLE hBsReader, + IVAS_DEC_HRTF_BINARY_WRAPPER *hHrtfBinary, + RotFileReader *headRotReader, + RotFileReader *externalOrientationFileReader, + RotFileReader *refRotReader, + Vector3PairFileReader *referenceVectorReader, + ObjectEditFileReader *objectEditFileReader, + ISAR_SPLIT_REND_BITS_DATA *splitRendBits, + IVAS_DEC_HANDLE hIvasDec, + int16_t *pcmBuf ); +static ivas_error decodeVoIP( + DecArguments arg, + BS_READER_HANDLE hBsReader, + IVAS_DEC_HRTF_BINARY_WRAPPER *hHrtf, + RotFileReader *headRotReader, + RotFileReader *externalOrientationFileReader, + RotFileReader *refRotReader, + Vector3PairFileReader *referenceVectorReader, + ObjectEditFileReader *objectEditFileReader, #ifdef FIX_1119_SPLIT_RENDERING_VOIP -static ivas_error decodeVoIP( DecArguments arg, BS_READER_HANDLE hBsReader, IVAS_DEC_HRTF_BINARY_WRAPPER *hHrtf, RotFileReader *headRotReader, RotFileReader *externalOrientationFileReader, RotFileReader *refRotReader, Vector3PairFileReader *referenceVectorReader, ObjectEditFileReader *objectEditFileReader, ISAR_SPLIT_REND_BITS_DATA *splitRendBits, IVAS_DEC_HANDLE hIvasDec, int16_t *pcmBuf ); + ISAR_SPLIT_REND_BITS_DATA *splitRendBits, +#endif +#ifdef FIX_SPLIT_RENDERING_ON_DECODER_RESTART + IVAS_RENDER_CONFIG_DATA *renderConfig, +#endif +#ifdef DECODER_FORMAT_SWITCHING + IVAS_DEC_HANDLE *phIvasDec, #else -static ivas_error decodeVoIP( DecArguments arg, BS_READER_HANDLE hBsReader, IVAS_DEC_HRTF_BINARY_WRAPPER *hHrtf, RotFileReader *headRotReader, RotFileReader *externalOrientationFileReader, RotFileReader *refRotReader, Vector3PairFileReader *referenceVectorReader, ObjectEditFileReader *objectEditFileReader, IVAS_DEC_HANDLE hIvasDec, int16_t *pcmBuf ); + IVAS_DEC_HANDLE hIvasDec, #endif + int16_t *pcmBuf ); static ivas_error load_hrtf_from_file( IVAS_DEC_HRTF_BINARY_WRAPPER *hHrtfBinary, IVAS_DEC_HANDLE hIvasDec, const IVAS_AUDIO_CONFIG OutputConfig, const int32_t output_Fs ); #ifdef DEBUGGING static ivas_error printBitstreamInfoVoip( DecArguments arg, BS_READER_HANDLE hBsReader, IVAS_DEC_HANDLE hIvasDec ); static int16_t app_own_random( int16_t *seed ); #endif static void do_object_editing( IVAS_EDITABLE_PARAMETERS *editableParameters, ObjectEditFileReader *objectEditFileReader ); +#ifdef DECODER_FORMAT_SWITCHING +static ivas_error restartDecoder( IVAS_DEC_HANDLE *phIvasDec, const IVAS_DEC_MODE decMode, DecArguments *arg, IVAS_RENDER_CONFIG_DATA *renderConfig, IVAS_CUSTOM_LS_DATA *hLsCustomData ); +#endif + /*------------------------------------------------------------------------------------------* * main() @@ -226,6 +267,13 @@ int main( IVAS_RENDER_FRAMESIZE asked_frame_size; IVAS_DEC_HRTF_BINARY_WRAPPER hHrtfBinary; ObjectEditFileReader *objectEditFileReader = NULL; +#ifdef IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT + IVAS_ROOM_ACOUSTICS_CONFIG_DATA **pAE = NULL; + uint32_t aeCount = 0; +#endif +#ifdef FIX_SPLIT_RENDERING_ON_DECODER_RESTART + IVAS_RENDER_CONFIG_DATA renderConfig = { 0 }; +#endif #ifdef DEBUGGING int32_t noClipping; int32_t cnt_frames_limited; @@ -450,14 +498,24 @@ int main( *------------------------------------------------------------------------------------------*/ asked_frame_size = arg.renderFramesize; +#ifdef IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT + uint16_t aeID = arg.aeSequence.count > 0 ? arg.aeSequence.pID[0] : IVAS_DEFAULT_AEID; +#else uint16_t aeID = arg.aeSequence.count > 0 ? arg.aeSequence.pID[0] : 65535; +#endif #ifdef IVAS_RTPDUMP arg.enableHeadRotation = arg.enableHeadRotation || arg.outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || arg.outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM; #endif +#ifdef FIX_1318_ROOM_SIZE_CMD_LINE + if ( ( error = IVAS_DEC_Configure( hIvasDec, arg.output_Fs, arg.outputConfig, arg.renderFramesize, arg.customLsOutputEnabled, arg.hrtfReaderEnabled, + arg.enableHeadRotation, arg.enableExternalOrientation, arg.orientation_tracking, arg.renderConfigEnabled, arg.roomSize, arg.non_diegetic_pan_enabled, + arg.non_diegetic_pan_gain, arg.dpidEnabled, aeID, arg.objEditEnabled, arg.delayCompensationEnabled ) ) != IVAS_ERR_OK ) +#else if ( ( error = IVAS_DEC_Configure( hIvasDec, arg.output_Fs, arg.outputConfig, arg.renderFramesize, arg.customLsOutputEnabled, arg.hrtfReaderEnabled, arg.enableHeadRotation, arg.enableExternalOrientation, arg.orientation_tracking, arg.renderConfigEnabled, arg.non_diegetic_pan_enabled, arg.non_diegetic_pan_gain, arg.dpidEnabled, aeID, arg.objEditEnabled, arg.delayCompensationEnabled ) ) != IVAS_ERR_OK ) +#endif { fprintf( stderr, "\nConfigure failed: %s\n\n", IVAS_DEC_GetErrorMessage( error ) ); goto cleanup; @@ -492,7 +550,6 @@ int main( fprintf( stderr, "\nConfigure failed: %s\n\n", IVAS_DEC_GetErrorMessage( error ) ); goto cleanup; } - #ifndef IVAS_RTPDUMP arg.enableHeadRotation = true; #endif @@ -604,7 +661,9 @@ int main( if ( arg.renderConfigEnabled ) { +#ifndef FIX_SPLIT_RENDERING_ON_DECODER_RESTART IVAS_RENDER_CONFIG_DATA renderConfig; +#endif /* sanity check */ if ( arg.outputConfig != IVAS_AUDIO_CONFIG_BINAURAL && arg.outputConfig != IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR && arg.outputConfig != IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB && @@ -632,6 +691,48 @@ int main( goto cleanup; } +#ifdef IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT + aeCount = RenderConfigReader_getAcousticEnvironmentCount( renderConfigReader ); + if ( aeCount > 0 ) + { + uint32_t n; + + pAE = malloc( aeCount * sizeof( IVAS_ROOM_ACOUSTICS_CONFIG_DATA * ) ); + + if ( pAE == NULL ) + { + fprintf( stderr, "\nError: cannot allocate memory for acoustic environment array\n\n" ); + goto cleanup; + } + + for ( n = 0; n < aeCount; n++ ) + { + pAE[n] = NULL; + + if ( NULL == ( pAE[n] = malloc( sizeof( IVAS_ROOM_ACOUSTICS_CONFIG_DATA ) ) ) ) + { + fprintf( stderr, "\nError: cannot allocate memory for acoustic environment\n\n" ); + goto cleanup; + } + } + + if ( ( error = RenderConfigReader_getAcousticEnvironments( renderConfigReader, pAE ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error while getting acoustic environments\n\n" ); + goto cleanup; + } + + for ( n = 0; n < aeCount; n++ ) + { + if ( ( error = IVAS_DEC_AddAcousticEnvironment( hIvasDec, *pAE[n] ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Failed to add acoustic environments\n\n" ); + goto cleanup; + } + } + } +#endif + if ( ( error = RenderConfigReader_getDirectivity( renderConfigReader, arg.directivityPatternId, renderConfig.directivity ) ) != IVAS_ERR_OK ) { fprintf( stderr, "Failed to get directivity patterns for one or more of IDs: %d %d %d %d\n\n", arg.directivityPatternId[0], arg.directivityPatternId[1], arg.directivityPatternId[2], arg.directivityPatternId[3] ); @@ -669,7 +770,11 @@ int main( if ( arg.outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) { +#ifdef IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT + if ( ( error = IVAS_DEC_GetAcousticEnvironment( hIvasDec, aeID, &renderConfig.roomAcoustics ) ) == IVAS_ERR_OK ) +#else if ( ( error = RenderConfigReader_getAcousticEnvironment( renderConfigReader, aeID, &renderConfig.roomAcoustics ) ) == IVAS_ERR_OK ) +#endif { if ( RenderConfigReader_checkValues( &renderConfig ) != IVAS_ERR_OK ) { @@ -754,12 +859,19 @@ int main( if ( arg.voipMode ) { - + error = decodeVoIP( arg, hBsReader, &hHrtfBinary, headRotReader, externalOrientationFileReader, refRotReader, referenceVectorReader, objectEditFileReader, #ifdef FIX_1119_SPLIT_RENDERING_VOIP - error = decodeVoIP( arg, hBsReader, &hHrtfBinary, headRotReader, externalOrientationFileReader, refRotReader, referenceVectorReader, objectEditFileReader, &splitRendBits, hIvasDec, pcmBuf ); + &splitRendBits, +#endif +#ifdef FIX_SPLIT_RENDERING_ON_DECODER_RESTART + &renderConfig, +#endif +#ifdef DECODER_FORMAT_SWITCHING + &hIvasDec, #else - error = decodeVoIP( arg, hBsReader, &hHrtfBinary, headRotReader, externalOrientationFileReader, refRotReader, referenceVectorReader, objectEditFileReader, hIvasDec, pcmBuf ); + hIvasDec, #endif + pcmBuf ); } else { @@ -804,6 +916,20 @@ cleanup: free( pcmBuf ); +#ifdef IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT + if ( pAE != NULL ) + { + uint16_t n; + + for ( n = 0; n < aeCount; n++ ) + { + free( pAE[n] ); + } + + free( pAE ); + } +#endif + if ( arg.aeSequence.count > 0 ) { free( arg.aeSequence.pID ); @@ -971,6 +1097,9 @@ static bool parseCmdlIVAS_dec( arg->output_Fs = IVAS_MAX_SAMPLING_RATE; arg->outputConfig = IVAS_AUDIO_CONFIG_MONO; arg->decMode = IVAS_DEC_MODE_IVAS; +#ifdef FIX_1419_MONO_STEREO_UMX + arg->evsMode = false; +#endif arg->quietModeEnabled = false; arg->delayCompensationEnabled = true; arg->voipMode = false; @@ -1036,6 +1165,10 @@ static bool parseCmdlIVAS_dec( arg->objEditEnabled = false; arg->objEditFileName = NULL; +#ifdef FIX_1318_ROOM_SIZE_CMD_LINE + arg->roomSize = IVAS_ROOM_SIZE_AUTO; +#endif + /*-----------------------------------------------------------------* * Initialization *-----------------------------------------------------------------*/ @@ -1524,6 +1657,53 @@ static bool parseCmdlIVAS_dec( } i++; } +#ifdef FIX_1419_MONO_STEREO_UMX + else if ( strcmp( argv_to_upper, "-EVS" ) == 0 ) + { + arg->evsMode = true; + arg->decMode = IVAS_DEC_MODE_EVS; + i++; + } +#endif +#ifdef FIX_1318_ROOM_SIZE_CMD_LINE + else if ( strcmp( argv_to_upper, "-ROOM_SIZE" ) == 0 ) + { + i++; + if ( argc - i <= 3 || argv[i][0] == '-' ) + { + fprintf( stderr, "Error: Room size selector not specified!\n\n" ); + usage_dec(); + return false; + } + + if ( strlen( argv[i] ) != 1 ) + { + fprintf( stderr, "Error: Unsupported room size selector %s!\n\n", argv[i] ); + usage_dec(); + return false; + } + switch ( argv[i][0] ) + { + case 'S': + case 's': + arg->roomSize = IVAS_ROOM_SIZE_SMALL; + break; + case 'M': + case 'm': + arg->roomSize = IVAS_ROOM_SIZE_MEDIUM; + break; + case 'L': + case 'l': + arg->roomSize = IVAS_ROOM_SIZE_LARGE; + break; + default: + fprintf( stderr, "Error: Unsupported room size selector %s!\n\n", argv[i] ); + usage_dec(); + return false; + } + i++; + } +#endif /*-----------------------------------------------------------------* * Option not recognized @@ -1574,6 +1754,14 @@ static bool parseCmdlIVAS_dec( usage_dec(); return false; } +#ifdef FIX_1419_MONO_STEREO_UMX + else if ( arg->non_diegetic_pan_enabled && arg->outputConfig == IVAS_AUDIO_CONFIG_STEREO && arg->evsMode ) + { + fprintf( stderr, "Error: Both non-diegetic panning and stereo output specified!\n\n" ); + usage_dec(); + return false; + } +#endif if ( arg->outputMdFilename != NULL && arg->outputConfig != IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) { @@ -1666,6 +1854,9 @@ static bool parseCmdlIVAS_dec( static void usage_dec( void ) { fprintf( stdout, "Usage for EVS: IVAS_dec.exe [Options] Fs bitstream_file output_file\n" ); +#ifdef FIX_1419_MONO_STEREO_UMX + fprintf( stdout, " OR usage for IVAS (below) with -evs option and OutputConf\n" ); +#endif fprintf( stdout, "Usage for IVAS: IVAS_dec.exe [Options] OutputConf Fs bitstream_file output_file\n\n" ); fprintf( stdout, "Mandatory parameters:\n" ); @@ -1682,6 +1873,9 @@ static void usage_dec( void ) fprintf( stdout, "Options:\n" ); fprintf( stdout, "--------\n" ); +#ifdef FIX_1419_MONO_STEREO_UMX + fprintf( stdout, "-evs : Specify that the supplied bitstream is an EVS bitstream\n" ); +#endif fprintf( stdout, "-VOIP : VoIP mode: RTP in G192\n" ); fprintf( stdout, "-VOIP_hf_only=0 : VoIP mode: EVS RTP Payload Format hf_only=0 in rtpdump\n" ); #ifdef IVAS_RTPDUMP @@ -1729,6 +1923,10 @@ static void usage_dec( void ) fprintf( stdout, "-rvf File : Reference vector specified by external trajectory File\n" ); fprintf( stdout, " works only in combination with '-otr ref_vec' and 'ref_vec_lev' modes\n" ); fprintf( stdout, "-render_config File : Renderer configuration File\n" ); +#ifdef FIX_1318_ROOM_SIZE_CMD_LINE + fprintf( stdout, "-room_size (S|M|L) : Selects default reverb based on a room size (S - small | M - medium | L - large)\n" ); + fprintf( stdout, " for BINAURAL_ROOM_REVERB output configuration,\n" ); +#endif fprintf( stdout, "-om File : Metadata output File for BINAURAL_SPLIT_PCM OutputConf (only for Fs = 48 kHz)\n" ); fprintf( stdout, "-non_diegetic_pan P : panning mono non-diegetic sound to stereo with panning P, -90<= P <=90,\n" ); fprintf( stdout, " left or l or 90->left, right or r or -90->right, center or c or 0->middle\n" ); @@ -1855,6 +2053,15 @@ static ivas_error initOnFirstGoodFrame( ISAR_SPLIT_REND_POSE_CORRECTION_MODE poseCorrection; int16_t splitRendIsarFrameSizeMs; int16_t lc3plusHighRes; + +#ifdef NONBE_FIX_BASOP_2233_RTPDUMP_DIFFERING_BITSTREAMS + /* Ideally ssrc is negotiated via SDP and sequence number is radomized but we + use fixed seed for random num generator for regression based tests. Any realtime + application should implement this initialization seperately */ + uint16_t rtpDecSeed = RANDOM_INITSEED_DEC; + uint32_t ssrc = ( (uint32_t) IVAS_RTP_OwnRandom( &rtpDecSeed ) & 0x0000FFFF ) | ( (uint32_t) IVAS_RTP_OwnRandom( &rtpDecSeed ) << 16 ); + uint16_t seqNumInitVal = IVAS_RTP_OwnRandom( &rtpDecSeed ); +#else #ifdef FIXED_RTP_SEQUENCE_NUM /* Ideally ssrc is negotiated via SDP and sequence number is radomized but we use fixed seed for random num generator for regression based tests. Any realtime @@ -1862,6 +2069,7 @@ static ivas_error initOnFirstGoodFrame( srand( RANDOM_INITSEED_DEC ); uint32_t ssrc = ( (uint32_t) rand() & 0x0000FFFF ) | ( (uint32_t) rand() << 16 ); uint16_t seqNumInitVal = (uint16_t) ( rand() & 0xFFFF ); +#endif #endif if ( ( error = IVAS_DEC_GetDelay( hIvasDec, delayNumSamples_temp, &delayTimeScale_temp ) ) != IVAS_ERR_OK ) @@ -1889,12 +2097,16 @@ static ivas_error initOnFirstGoodFrame( fParamsSR = fopen( srParamsFile, "w" ); if ( NULL != fParamsSR ) { +#ifdef RTP_SR_CODEC_FRAME_SIZE_IN_TOC_BYTE + fprintf( fParamsSR, "DOF = %d;\nLC3PLUS_HIGHRES = %d;\n", poseCorrection, lc3plusHighRes ); +#else fprintf( fParamsSR, "CODEC = %s;\nDOF = %d;\nFRAMESIZE = %d;\nRENDERSIZE = %d;\nLC3PLUS_HIGHRES = %d;\n", splitRendCodec == ISAR_SPLIT_REND_CODEC_LC3PLUS ? "LC3PLUS" : "LCLD", poseCorrection, splitRendCodecFrameSizeMs, splitRendIsarFrameSizeMs, lc3plusHighRes ); +#endif fclose( fParamsSR ); fParamsSR = NULL; } @@ -2438,7 +2650,7 @@ static ivas_error decodeG192( fprintf( stderr, "\nIVAS_DEC_GetNumOrientationSubframes failed: \n" ); goto cleanup; } - /* Head-tracking input simulation */ + /* Head-tracking input simulation */ if ( arg.enableHeadRotation ) { @@ -3093,8 +3305,10 @@ static ivas_error printBitstreamInfoVoip( case IVAS_DEC_INPUT_FORMAT_RTPDUMP: case IVAS_DEC_INPUT_FORMAT_RTPDUMP_HF: #ifdef IVAS_RTPDUMP +#ifndef RTP_SR_CODEC_FRAME_SIZE_IN_TOC_BYTE #ifdef RTP_S4_251135_CR26253_0016_REV1 if ( ( error = IVAS_RTP_READER_Init( &ivasRtp, 0, arg.inputBitstreamFilename, arg.piOutputFilename, arg.outputConfig == IVAS_AUDIO_CONFIG_EXTERNAL, arg.outputWavFilename ) ) != IVAS_ERR_OK ) +#endif #else if ( ( error = IVAS_RTP_READER_Init( &ivasRtp, arg.inputBitstreamFilename, arg.piOutputFilename, arg.outputConfig == IVAS_AUDIO_CONFIG_EXTERNAL, arg.outputWavFilename ) ) != IVAS_ERR_OK ) #endif @@ -3215,7 +3429,14 @@ static ivas_error decodeVoIP( #ifdef FIX_1119_SPLIT_RENDERING_VOIP ISAR_SPLIT_REND_BITS_DATA *splitRendBits, #endif +#ifdef FIX_SPLIT_RENDERING_ON_DECODER_RESTART + IVAS_RENDER_CONFIG_DATA *renderConfig, +#endif +#ifdef DECODER_FORMAT_SWITCHING + IVAS_DEC_HANDLE *phIvasDec, +#else IVAS_DEC_HANDLE hIvasDec, +#endif int16_t *pcmBuf ) { bool decodingFailed = true; /* Assume failure until cleanup is reached without errors */ @@ -3247,10 +3468,18 @@ static ivas_error decodeVoIP( int16_t delayNumSamples = -1; int32_t delayTimeScale = -1; int16_t i; +#ifdef DECODER_FORMAT_SWITCHING + IVAS_DEC_HANDLE hIvasDec = *phIvasDec; + bool restartNeeded; +#endif #ifdef IVAS_RTPDUMP IVAS_RTP ivasRtp = { 0 }; IVAS_RTP srRtp = { 0 }; +#ifdef RTP_SR_CODEC_FRAME_SIZE_IN_TOC_BYTE + IVAS_RTP_SR_INFO srInfo = { true, false, 0, 20, IVAS_SR_TRANSPORT_LCLD }; +#else IVAS_RTP_SR_INFO srInfo = { true, false, 0, IVAS_SR_TRANSPORT_LCLD }; +#endif int32_t initialTsOffsetSystemAndRTP = 0; #else FILE *f_rtpstream = NULL; @@ -3330,8 +3559,10 @@ static ivas_error decodeVoIP( case IVAS_DEC_INPUT_FORMAT_RTPDUMP: case IVAS_DEC_INPUT_FORMAT_RTPDUMP_HF: #ifdef IVAS_RTPDUMP +#ifndef RTP_SR_CODEC_FRAME_SIZE_IN_TOC_BYTE #ifdef RTP_S4_251135_CR26253_0016_REV1 if ( ( error = IVAS_RTP_READER_Init( &ivasRtp, 0, arg.inputBitstreamFilename, arg.piOutputFilename, arg.outputConfig == IVAS_AUDIO_CONFIG_EXTERNAL, arg.outputWavFilename ) ) != IVAS_ERR_OK ) +#endif #else if ( ( error = IVAS_RTP_READER_Init( &ivasRtp, arg.inputBitstreamFilename, arg.piOutputFilename, arg.outputConfig == IVAS_AUDIO_CONFIG_EXTERNAL, arg.outputWavFilename ) ) != IVAS_ERR_OK ) #endif @@ -3443,6 +3674,32 @@ static ivas_error decodeVoIP( { nSamplesRendered = 0; +#ifdef DECODER_FORMAT_SWITCHING + /* restart decoder in case of format switching */ + if ( ivasRtp.restartNeeded ) + { + IVAS_DEC_MODE newDecModeInPacket = ( ivasRtp.codecId == IVAS_RTP_EVS ) ? IVAS_DEC_MODE_EVS : IVAS_DEC_MODE_IVAS; + if ( ( error = restartDecoder( + &hIvasDec, + newDecModeInPacket, + &arg, +#ifdef FIX_SPLIT_RENDERING_ON_DECODER_RESTART + renderConfig, +#else + NULL, /* ToDo : Provide rendererConfig */ +#endif + NULL /* ToDo : Provide LS Custom Data */ + ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nFailed to restart decoder from %d to %d\n", arg.decMode, newDecModeInPacket ); + goto cleanup; + } + + *phIvasDec = hIvasDec; /* Update for main()' s free */ + ivasRtp.restartNeeded = false; + } +#endif + /* reference vector */ if ( arg.enableReferenceVectorTracking && vec_pos_update == 0 ) { @@ -3476,6 +3733,7 @@ static ivas_error decodeVoIP( goto cleanup; } } + int16_t num_subframes; if ( ( error = IVAS_DEC_GetNumOrientationSubframes( hIvasDec, &num_subframes ) ) != IVAS_ERR_OK ) { @@ -3483,7 +3741,6 @@ static ivas_error decodeVoIP( goto cleanup; } - /* Head-tracking input simulation */ /* Head-tracking input simulation */ if ( arg.enableHeadRotation ) { @@ -3625,12 +3882,17 @@ static ivas_error decodeVoIP( /* we are finished when all packets have been received and jitter buffer is empty */ /* also stop when the input file contains less than two frames, because JBM cannot calculate a delay value and won't start decoding */ /* last clause should make sure that for BE tests we end up with the same number of samples...*/ - if ( nextPacketRcvTime_ms == (uint32_t) ( -1 ) && ( IVAS_DEC_VoIP_IsEmpty( hIvasDec, nOutSamples ) || nFramesFed < 2 ) ) + bool isEmpty; + if ( ( error = IVAS_DEC_VoIP_IsEmpty( hIvasDec, nOutSamples, &isEmpty ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError in IVAS_DEC_VoIP_GetSamples: %s\n", IVAS_DEC_GetErrorMessage( error ) ); + goto cleanup; + } + if ( nextPacketRcvTime_ms == (uint32_t) ( -1 ) && ( isEmpty || nFramesFed < 2 ) ) { break; } - /* decode and get samples */ while ( nSamplesRendered < nOutSamples ) { @@ -3647,7 +3909,7 @@ static ivas_error decodeVoIP( numPiData++; } - if ( ( error = IVAS_RTP_FeedPiDataToDecoder( hIvasDec, &ivasRtp.piData[ivasRtp.nProcPiData], numPiData ) ) != IVAS_ERR_OK ) + if ( ( error = IVAS_DEC_FeedPiDataToDecoder( hIvasDec, &ivasRtp.piData[ivasRtp.nProcPiData], numPiData ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nError in IVAS_DEC_VoIP_GetSamples: %s\n", IVAS_DEC_GetErrorMessage( error ) ); goto cleanup; @@ -3695,6 +3957,38 @@ static ivas_error decodeVoIP( return error; } +#ifdef DECODER_FORMAT_SWITCHING + /* restart decoder in case of format switching */ + if ( ( error = IVAS_DEC_isRestartNeeded( hIvasDec, &restartNeeded ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( restartNeeded ) + { + IVAS_DEC_BS_FORMAT tempBsFormat; + if ( ( error = IVAS_DEC_GetFormat( hIvasDec, &tempBsFormat ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError in IVAS_DEC_GetFormat, code: %d\n", error ); + goto cleanup; + } + + IVAS_DEC_MODE newDecModeInPacket = ( tempBsFormat == IVAS_DEC_BS_MONO ) ? IVAS_DEC_MODE_EVS : IVAS_DEC_MODE_IVAS; + if ( ( error = restartDecoder( + &hIvasDec, + newDecModeInPacket, + &arg, + NULL, /* ToDo : Provide rendererConfig */ + NULL /* ToDo : Provide LS Custom Data */ + ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nFailed to restart decoder\n" ); + goto cleanup; + } + *phIvasDec = hIvasDec; /* Update for main()' s free */ + } +#endif + /* Placeholder for memory reallocation */ /* ... */ @@ -3887,6 +4181,7 @@ static ivas_error decodeVoIP( { srInfo.bitrateKbps = splitRendBits->bits_written * 1000 / splitRendBits->codec_frame_size_ms; srInfo.codec = ( splitRendBits->codec == ISAR_SPLIT_REND_CODEC_LC3PLUS ) ? IVAS_SR_TRANSPORT_LC3PLUS : IVAS_SR_TRANSPORT_LCLD; + srInfo.codecFrameSizeMs = (uint32_t) splitRendBits->codec_frame_size_ms; if ( ( error = IVAS_RTP_WriteNextFrame( &srRtp, splitRendBits->bits_buf, &srInfo, (int16_t) splitRendBits->bits_written, false, false ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nError %s while pushing SR audio bitstream to RTP pack\n", ivas_error_to_string( error ) ); @@ -3897,7 +4192,6 @@ static ivas_error decodeVoIP( } #endif - vec_pos_update = ( vec_pos_update + 1 ) % vec_pos_len; if ( vec_pos_update == 0 ) { @@ -4154,6 +4448,46 @@ static void do_object_editing( editableParameters->ism_metadata[obj_idx].elevation = readInfo->obj_ele[obj_idx]; } } +#ifdef FIX_1427_OBJ_EDITING_EXT_METADATA + /* object direction editing only for diegetic objects */ + if ( readInfo->obj_yaw_edited[obj_idx] ) + { + if ( readInfo->obj_yaw_relative[obj_idx] ) + { + /* yaw: apply relative edit + wrap */ + editableParameters->ism_metadata[obj_idx].yaw = fmodf( editableParameters->ism_metadata[obj_idx].yaw + readInfo->obj_yaw[obj_idx] + 540.f, 360.f ) - 180.f; + } + else + { + editableParameters->ism_metadata[obj_idx].yaw = readInfo->obj_yaw[obj_idx]; + } + } + if ( readInfo->obj_pitch_edited[obj_idx] ) + { + if ( readInfo->obj_pitch_relative[obj_idx] ) + { + /* pitch: apply relative edit + saturation */ + editableParameters->ism_metadata[obj_idx].pitch = fmaxf( fminf( editableParameters->ism_metadata[obj_idx].pitch + readInfo->obj_pitch[obj_idx], 90.f ), -90.f ); + } + else + { + editableParameters->ism_metadata[obj_idx].pitch = readInfo->obj_pitch[obj_idx]; + } + } + /* radius editing only for diegetic objects */ + if ( readInfo->obj_radius_edited[obj_idx] ) + { + if ( readInfo->obj_radius_relative[obj_idx] ) + { + /* radius: apply relative edit + saturation */ + editableParameters->ism_metadata[obj_idx].radius = fmaxf( fminf( editableParameters->ism_metadata[obj_idx].radius * readInfo->obj_radius[obj_idx], OBJ_EDIT_RADIUS_MAX ), 0.0f ); + } + else + { + editableParameters->ism_metadata[obj_idx].radius = readInfo->obj_radius[obj_idx]; + } + } +#endif } /* gain editing for all objects */ @@ -4375,4 +4709,134 @@ static ivas_error load_hrtf_from_file( return IVAS_ERR_OK; } +#ifdef DECODER_FORMAT_SWITCHING + +/*---------------------------------------------------------------------* + * restartDecoder() + * + * Restart decoder in case of IVAS format switching + *---------------------------------------------------------------------*/ + +static ivas_error restartDecoder( + IVAS_DEC_HANDLE *phIvasDec, + const IVAS_DEC_MODE decMode, + DecArguments *arg, + IVAS_RENDER_CONFIG_DATA *renderConfig, + IVAS_CUSTOM_LS_DATA *hLsCustomData ) +{ + ivas_error error = IVAS_ERR_OK; + IVAS_DEC_HANDLE hIvasDec; + + if ( phIvasDec == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + if ( NULL != *phIvasDec ) + { + IVAS_DEC_Close( phIvasDec ); + } + + if ( ( error = IVAS_DEC_Open( phIvasDec, decMode ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Open failed: %s\n", IVAS_DEC_GetErrorMessage( error ) ); + goto cleanup; + } + + arg->decMode = decMode; + + hIvasDec = *phIvasDec; + + uint16_t aeID = arg->aeSequence.count > 0 ? arg->aeSequence.pID[0] : 65535; + + IVAS_AUDIO_CONFIG outputConfig = ( decMode == IVAS_DEC_MODE_IVAS ) ? arg->outputConfig : IVAS_AUDIO_CONFIG_MONO; +#ifdef FIX_1318_ROOM_SIZE_CMD_LINE + if ( ( error = IVAS_DEC_Configure( hIvasDec, arg->output_Fs, outputConfig, arg->renderFramesize, arg->customLsOutputEnabled, arg->hrtfReaderEnabled, + arg->enableHeadRotation, arg->enableExternalOrientation, arg->orientation_tracking, arg->renderConfigEnabled, arg->roomSize, arg->non_diegetic_pan_enabled, + arg->non_diegetic_pan_gain, arg->dpidEnabled, aeID, arg->objEditEnabled, arg->delayCompensationEnabled ) ) != IVAS_ERR_OK ) +#else + if ( ( error = IVAS_DEC_Configure( hIvasDec, arg->output_Fs, outputConfig, arg->renderFramesize, arg->customLsOutputEnabled, arg->hrtfReaderEnabled, + arg->enableHeadRotation, arg->enableExternalOrientation, arg->orientation_tracking, arg->renderConfigEnabled, arg->non_diegetic_pan_enabled, + arg->non_diegetic_pan_gain, arg->dpidEnabled, aeID, arg->objEditEnabled, arg->delayCompensationEnabled ) ) != IVAS_ERR_OK ) +#endif + { + fprintf( stderr, "\nConfigure failed: %s\n\n", IVAS_DEC_GetErrorMessage( error ) ); + goto cleanup; + } + + if ( ( error = IVAS_DEC_GetRenderFramesize( hIvasDec, &arg->renderFramesize ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nConfigure failed: %s\n\n", IVAS_DEC_GetErrorMessage( error ) ); + goto cleanup; + } + +#ifndef FIX_SPLIT_RENDERING_ON_DECODER_RESTART + if ( arg->outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || arg->outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) + { + if ( ( error = IVAS_DEC_EnableSplitRendering( hIvasDec ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nSplit rendering configure failed: %s\n\n", IVAS_DEC_GetErrorMessage( error ) ); + goto cleanup; + } + + if ( ( error = IVAS_DEC_GetRenderFramesize( hIvasDec, &arg->renderFramesize ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nConfigure failed: %s\n\n", IVAS_DEC_GetErrorMessage( error ) ); + goto cleanup; + } + + arg->enableHeadRotation = true; + } +#endif + + if ( arg->voipMode ) + { + if ( ( error = IVAS_DEC_EnableVoIP( hIvasDec, 60, arg->inputFormat ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nCould not enable VOIP: %s\n\n", IVAS_DEC_GetErrorMessage( error ) ); + goto cleanup; + } + } + + if ( ( error = IVAS_DEC_PrintConfig( hIvasDec, 1, arg->voipMode ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nIVAS_DEC_PrintConfig failed: %s\n\n", IVAS_DEC_GetErrorMessage( error ) ); + goto cleanup; + } + +#ifdef FIX_SPLIT_RENDERING_ON_DECODER_RESTART + /* ISAR frame size is set from command line, not renderer config file. + * This will be ignored if output format is not split rendering. */ + if ( renderConfig != NULL ) + { + renderConfig->split_rend_config.isar_frame_size_ms = (int16_t) arg->renderFramesize /* given in number of 5ms subframes */ * 5; + } +#endif + + if ( arg->renderConfigEnabled && renderConfig != NULL ) + { + if ( ( error = IVAS_DEC_FeedRenderConfig( hIvasDec, *renderConfig ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nIVAS_DEC_FeedRenderConfig failed: %s\n\n", IVAS_DEC_GetErrorMessage( error ) ); + goto cleanup; + } + } + + if ( arg->customLsOutputEnabled && hLsCustomData != NULL ) + { + if ( ( error = IVAS_DEC_FeedCustomLsData( hIvasDec, *hLsCustomData ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nIVAS_DEC_FeedCustomLsData failed: %s\n", IVAS_DEC_GetErrorMessage( error ) ); + goto cleanup; + } + } + + return IVAS_ERR_OK; + +cleanup: + IVAS_DEC_Close( phIvasDec ); + return error; +} +#endif + #undef WMC_TOOL_SKIP diff --git a/apps/encoder.c b/apps/encoder.c index 162ac9a19dfd4e83a2fbbd46d30e81ca78a7f45e..2c9c42b462a56e4a5e1d4cd83e08d86f49f9120d 100644 --- a/apps/encoder.c +++ b/apps/encoder.c @@ -50,10 +50,6 @@ #include "flp_debug.h" #endif -#ifdef FIXED_RTP_SEQUENCE_NUM -#define RANDOM_INITSEED_ENC ( 0xFEEDDEAF ) -#endif - #define WMC_TOOL_SKIP /*------------------------------------------------------------------------------------------* @@ -65,6 +61,14 @@ static #endif int32_t frame = 0; /* Counter of frames */ +#ifdef NONBE_FIX_BASOP_2233_RTPDUMP_DIFFERING_BITSTREAMS +#define RANDOM_INITSEED_ENC ( 0xDEAF ) +#else +#ifdef FIXED_RTP_SEQUENCE_NUM +#define RANDOM_INITSEED_ENC ( 0xFEEDDEAF ) +#endif +#endif + #define DEFAULT_FIXED_SID_RATE 8 /* DTX SID rate */ /* Additional config info for each input format */ @@ -234,6 +238,14 @@ int main( IVAS_RTP ivasRtp = { 0 }; #endif +#ifdef NONBE_FIX_BASOP_2233_RTPDUMP_DIFFERING_BITSTREAMS + /* Ideally ssrc is negotiated via SDP and sequence number is radomized but we + use fixed seed for random num generator for regression based tests. Any realtime + application should implement this initialization seperately */ + uint16_t rtpEncSeed = RANDOM_INITSEED_ENC; + uint32_t ssrc = ( (uint32_t) IVAS_RTP_OwnRandom( &rtpEncSeed ) & 0x0000FFFF ) | ( (uint32_t) IVAS_RTP_OwnRandom( &rtpEncSeed ) << 16 ); + uint16_t seqNumInitVal = IVAS_RTP_OwnRandom( &rtpEncSeed ); +#else #ifdef FIXED_RTP_SEQUENCE_NUM /* Ideally ssrc is negotiated via SDP and sequence number is radomized but we use fixed seed for random num generator for regression based tests. Any realtime @@ -241,6 +253,7 @@ int main( srand( RANDOM_INITSEED_ENC ); uint32_t ssrc = ( (uint32_t) rand() & 0x0000FFFF ) | ( (uint32_t) rand() << 16 ); uint16_t seqNumInitVal = (uint16_t) ( rand() & 0xFFFF ); +#endif #endif /*------------------------------------------------------------------------------------------* @@ -474,14 +487,14 @@ int main( if ( ( error = IVAS_ENC_ConfigureForSBAObjects( hIvasEnc, arg.inputFs, totalBitrate, bandwidth, arg.dtxConfig, arg.inputFormatConfig.sba_ism.numObjects, arg.inputFormatConfig.sba_ism.order, arg.inputFormatConfig.sba_ism.isPlanar, arg.pca ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nIVAS_ENC_ConfigureForSBAObjects failed: %s\n\n", IVAS_ENC_GetErrorMessage( error ) ); - exit( -1 ); + goto cleanup; } break; 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 ); + goto cleanup; } break; default: @@ -678,6 +691,10 @@ int main( } #endif + /*------------------------------------------------------------------------------------------* + * Run the encoder + *------------------------------------------------------------------------------------------*/ + int16_t numSamplesRead = 0; uint16_t bitStream[IVAS_MAX_BITS_PER_FRAME]; uint16_t numBits = 0; @@ -1084,7 +1101,6 @@ static bool parseCmdlIVAS_enc( arg->sceneOrientationTrajFileName = NULL; arg->deviceOrientationTrajFileName = NULL; #endif - #ifdef DEBUGGING arg->forcedMode = IVAS_ENC_FORCE_UNFORCED; arg->forcedModeFile = NULL; @@ -1887,6 +1903,7 @@ static bool parseCmdlIVAS_enc( { i++; arg->rtpdumpOutput = true; + if ( i < argc - 4 ) { if ( !is_digits_only( argv[i] ) ) @@ -1903,6 +1920,7 @@ static bool parseCmdlIVAS_enc( } } } + fprintf( stdout, "Output format: RTPDump using %d frames/packet \n", arg->numFramesPerPacket ); } @@ -1961,6 +1979,7 @@ static bool parseCmdlIVAS_enc( usage_enc(); return false; } + if ( arg->deviceOrientationTrajFileName != NULL && arg->rtpdumpOutput == false ) { fprintf( stderr, "Error: Device orientations are only enabled with rtpdump output!\n\n" ); diff --git a/apps/encoder_fmtsw.c b/apps/encoder_fmtsw.c new file mode 100644 index 0000000000000000000000000000000000000000..1730018f8e4bd4b255f0445b211ccafdf230390b --- /dev/null +++ b/apps/encoder_fmtsw.c @@ -0,0 +1,2498 @@ +/****************************************************************************************************** + + (C) 2022-2025 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +#include "lib_enc.h" +#include +#include "cmdl_tools.h" +#include "audio_file_reader.h" +#include "bitstream_writer.h" +#include "ism_file_reader.h" +#include "jbm_file_reader.h" +#include "masa_file_reader.h" +#ifdef IVAS_RTPDUMP +#include "rotation_file_reader.h" +#include "ivas_rtp_file.h" +#endif +#ifdef DEBUGGING +#include "debug.h" +#endif +#include "wmc_auto.h" +#ifdef FLP_EXCEPTION_TRAP +#include "flp_debug.h" +#endif + +#define WMC_TOOL_SKIP + +/*------------------------------------------------------------------------------------------* + * Local constants, enums + *------------------------------------------------------------------------------------------*/ + +#define MAX_ARGV 20 /* maximum number of command line arguments that can be \ + in one line of the format switching file */ + +#if !defined( DEBUGGING ) && !defined( WMOPS ) +static +#endif + int32_t frame = 0; /* Counter of frames */ + +#ifdef NONBE_FIX_BASOP_2233_RTPDUMP_DIFFERING_BITSTREAMS +#define RANDOM_INITSEED_ENC ( 0xDEAF ) +#else +#ifdef FIXED_RTP_SEQUENCE_NUM +#define RANDOM_INITSEED_ENC ( 0xFEEDDEAF ) +#endif +#endif + +#define DEFAULT_FIXED_SID_RATE 8 /* DTX SID rate */ + +/* Additional config info for each input format */ +typedef union _EncInputFormatConfig +{ + /* MONO details */ + bool stereoToMonoDownmix; + +#ifdef DEBUGGING + /* STEREO details */ + IVAS_ENC_STEREO_MODE stereoMode; +#endif + + /* ISM details */ + struct EncIsmConfig + { + int16_t numObjects; + const char *metadataFiles[IVAS_MAX_NUM_OBJECTS]; + } ism; + + /* SBA details */ + struct EncSbaConfig + { + IVAS_ENC_SBA_ORDER order; + bool isPlanar; + } sba; + + /* MASA details */ + IVAS_ENC_MASA_VARIANT masaVariant; + + /* MC details */ + IVAS_ENC_MC_LAYOUT mcLayout; + + struct EncMasaIsmConfig + { + int16_t numObjects; + const char *metadataFiles[IVAS_MAX_NUM_OBJECTS]; + IVAS_ENC_MASA_VARIANT masaVariant; + } masa_ism; + + struct EncSbaIsmConfig + { + int16_t numObjects; + const char *metadataFiles[IVAS_MAX_NUM_OBJECTS]; + IVAS_ENC_SBA_ORDER order; + bool isPlanar; + } sba_ism; + +} EncInputFormatConfig; + + +/*------------------------------------------------------------------------------------------* + * Local structure for storing cmdln arguments + *------------------------------------------------------------------------------------------*/ + +typedef struct +{ + char *inputWavFilename; + char *outputBitstreamFilename; + int32_t inputFs; + IVAS_ENC_INPUT_FORMAT inputFormat; + bool is_binaural; + EncInputFormatConfig inputFormatConfig; + bool max_bwidth_user; + IVAS_ENC_BANDWIDTH maxBandwidth; + const char *bandwithProfileFile; + IVAS_ENC_DTX_CONFIG dtxConfig; + int32_t initBitrate; + const char *bitrateProfileFile; + bool quietModeEnabled; + bool delayCompensationEnabled; + const char *masaMetadataFile; + IVAS_ENC_CHANNEL_AWARE_CONFIG caConfig; + const char *ca_config_file; + bool mimeOutput; + IVAS_ENC_COMPLEXITY_LEVEL complexityLevel; +#ifdef DEBUGGING + IVAS_ENC_FORCED_MODE forcedMode; + const char *forcedModeFile; +#ifdef DEBUG_AGC_ENCODER_CMD_OPTION + IVAS_ENC_AGC agc; +#endif +#ifdef DEBUG_FOA_AGC + FILE *agcBitstream; /* temporary */ +#endif +#ifdef DEBUG_SBA + const char *dbg_file_tag; +#endif +#endif + bool pca; + bool ism_extended_metadata; +#ifdef IVAS_RTPDUMP + bool rtpdumpOutput; + uint32_t numFramesPerPacket; + char *sceneOrientationTrajFileName; + char *deviceOrientationTrajFileName; +#endif + +} EncArguments; + + +/*------------------------------------------------------------------------------------------* + * Local functions prototypes + *------------------------------------------------------------------------------------------*/ + +static bool parseCmdlIVAS_enc( int16_t argc, char *argv[], EncArguments *arg ); +static void usage_enc( void ); +static bool readBandwidth( FILE *file, IVAS_ENC_BANDWIDTH *bandwidth, int32_t *bandwidthFrameCounter ); +static bool readBitrate( FILE *file, int32_t *bitrate ); +#ifdef DEBUGGING +static ivas_error readForcedMode( FILE *file, IVAS_ENC_FORCED_MODE *forcedMode, int32_t *forceFrameCounter ); +static IVAS_ENC_FORCED_MODE parseForcedMode( char *forcedModeChar ); +#endif +static void str2arg( char *str, int *argc_local, char *argv_local[] ); +#ifdef IVAS_RTPDUMP +static int encoder_main( int argc, char *argv[], IVAS_RTP *ivasRtp, int init_RtpWriter ); +#else +static int encoder_main( int argc, char *argv[] ); +#endif + + +/*------------------------------------------------------------------------------------------* + * main() + * + * Main IVAS encoder function for command-line interface + * supporting IVAS format switching + *------------------------------------------------------------------------------------------*/ + +int main( + int argc, + char *argv[] ) +{ + bool mainFailed = true; /* Assume main failed until cleanup is reached without errors */ + FILE *FmtSWFile = NULL; + char line[2048]; + int argc_local = 0; + char *argv_local[MAX_ARGV] = { 0 }; +#ifdef IVAS_RTPDUMP + IVAS_RTP ivasRtp = { 0 }; + char prev_outputBitstreamFilename[2048] = { 0 }; + int rtp_term = 0; +#endif + + IVAS_ENC_PrintDisclaimer(); + + if ( argc != 2 ) + { + fprintf( stdout, "Usage: IVAS_cod_fmtsw.exe format_switching_file\n\n" ); + fprintf( stdout, "where format_switching_file is a text file containg a valid encoder command line in each line\n\n" ); + goto cleanup; + } + fprintf( stdout, "Input format switching file: %s\n", argv[1] ); + + if ( ( FmtSWFile = fopen( argv[1], "r" ) ) == NULL ) + { + fprintf( stdout, "error: cannot open format switching file %s\n", argv[1] ); + goto cleanup; + } + + while ( fgets( line, sizeof( line ), FmtSWFile ) ) + { + /* remove trimming newline */ + line[strcspn( line, "\r\n" )] = 0; + printf( "Processing format switching commandline: %s\n", line ); + str2arg( line, &argc_local, argv_local ); +#ifdef IVAS_RTPDUMP + if ( strcmp( argv_local[argc_local - 1], (char *) prev_outputBitstreamFilename ) == 0 ) + { + /* append to last Rtp file */ + if ( encoder_main( argc_local, argv_local, &ivasRtp, 0 ) != 0 ) + { + goto cleanup; + } + } + else + { + if ( rtp_term == 1 ) + { + IVAS_RTP_Term( &ivasRtp ); + } + + /* write in separate Rtp file */ + if ( encoder_main( argc_local, argv_local, &ivasRtp, 1 ) != 0 ) + { + goto cleanup; + } + + rtp_term = 1; + } + strcpy( (char *) prev_outputBitstreamFilename, argv_local[argc_local - 1] ); +#else + encoder_main( argc_local, argv_local ); +#endif + } + + /*------------------------------------------------------------------------------------------* + * Close files and deallocate resources + *------------------------------------------------------------------------------------------*/ + + mainFailed = false; /* This will stay set to true if cleanup is reached via a goto due to an error */ + +cleanup: + +#ifdef IVAS_RTPDUMP + IVAS_RTP_Term( &ivasRtp ); +#endif + if ( FmtSWFile ) + { + fclose( FmtSWFile ); + } + + return mainFailed ? -1 : 0; +} + + +/*-------------------------------------------------------------------* + * Local functions + *-------------------------------------------------------------------*/ + +void str2arg( + char *str, /* input string */ + int *argc_local, /* number of argument */ + char *argv_local[] /* array of arguments */ +) +{ + int i = 0; + char *token = strtok( str, " " ); + while ( token && ( i < MAX_ARGV - 1 ) ) + { + argv_local[i++] = token; + token = strtok( 0, " " ); + } + argv_local[i] = 0; + *argc_local = i; + return; +} + +int encoder_main( + int argc, +#ifdef IVAS_RTPDUMP + char *argv[], + IVAS_RTP *ivasRtp, + int init_RtpWriter ) +#else + char *argv[] ) +#endif +{ + bool mainFailed = true; /* Assume main failed until cleanup is reached without errors */ + EncArguments arg; + int16_t i; + ivas_error error = IVAS_ERR_UNKNOWN; + + /* Any handles that require cleanup must be declared here and initialized to NULL */ + IVAS_ENC_HANDLE hIvasEnc = NULL; + BS_WRITER_HANDLE hBsWriter = NULL; + AudioFileReader *audioReader = NULL; + FILE *f_bitrateProfile = NULL; + FILE *f_bwProfile = NULL; + JbmFileReader *jbmReader = NULL; + MasaFileReader *masaReader = NULL; + IsmFileReader *ismReaders[IVAS_MAX_NUM_OBJECTS] = { NULL, NULL, NULL, NULL }; + int16_t *pcmBuf = NULL; +#ifdef IVAS_RTPDUMP + RotFileReader *sceneOrientationFileReader = NULL; + RotFileReader *deviceOrientationFileReader = NULL; +#endif +#ifdef DEBUGGING + FILE *f_forcedModeProfile = NULL; +#ifdef DEBUG_SBA + int16_t numTransportChannels = 1; +#endif + int32_t noClipping; + float maxOverload, minOverload; +#endif + +#ifdef DEBUGGING + dbgargs( &argc, argv ); +#endif +#ifdef WMOPS + reset_wmops(); + reset_mem( USE_BYTES ); +#endif +#ifdef FLP_EXCEPTION_TRAP + enable_float_exception_trap( FLE_MASK_DENORM | FLE_MASK_UNDERFLOW ); +#endif + +#ifdef IVAS_RTPDUMP + uint8_t au[IVAS_MAX_BITS_PER_FRAME / 8]; + /* IVAS_RTP ivasRtp = { 0 }; */ +#endif + +#ifdef NONBE_FIX_BASOP_2233_RTPDUMP_DIFFERING_BITSTREAMS + /* Ideally ssrc is negotiated via SDP and sequence number is radomized but we + use fixed seed for random num generator for regression based tests. Any realtime + application should implement this initialization seperately */ + uint16_t rtpEncSeed = RANDOM_INITSEED_ENC; + uint32_t ssrc = ( (uint32_t) IVAS_RTP_OwnRandom( &rtpEncSeed ) & 0x0000FFFF ) | ( (uint32_t) IVAS_RTP_OwnRandom( &rtpEncSeed ) << 16 ); + uint16_t seqNumInitVal = IVAS_RTP_OwnRandom( &rtpEncSeed ); +#else +#ifdef FIXED_RTP_SEQUENCE_NUM + /* Ideally ssrc is negotiated via SDP and sequence number is radomized but we + use fixed seed for random num generator for regression based tests. Any realtime + application should implement this initialization seperately */ + srand( RANDOM_INITSEED_ENC ); + uint32_t ssrc = ( (uint32_t) rand() & 0x0000FFFF ) | ( (uint32_t) rand() << 16 ); + uint16_t seqNumInitVal = (uint16_t) ( rand() & 0xFFFF ); +#endif +#endif + + /*------------------------------------------------------------------------------------------* + * Parse command-line arguments + *------------------------------------------------------------------------------------------*/ + + + if ( !parseCmdlIVAS_enc( (int16_t) argc, argv, &arg ) ) + { + /* Error printout done internally in parseCmdlIVAS_enc() */ + goto cleanup; + } + + /*------------------------------------------------------------------------------------------* + * Open and initialize IVAS encoder + *------------------------------------------------------------------------------------------*/ + + if ( ( error = IVAS_ENC_Open( &hIvasEnc ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Opening IVAS encoder failed: %s\n", IVAS_ENC_GetErrorMessage( error ) ); + goto cleanup; + } + + /*------------------------------------------------------------------------------------------* + * Open output bitstream file + *------------------------------------------------------------------------------------------*/ + const BS_WRITER_FORMAT bsWriterFormat = arg.mimeOutput ? BS_WRITER_FORMAT_MIME : BS_WRITER_FORMAT_G192; + +#ifdef IVAS_RTPDUMP + if ( !arg.rtpdumpOutput && BS_Writer_Open_filename( &hBsWriter, arg.outputBitstreamFilename, bsWriterFormat ) != IVAS_ERR_OK ) +#else + if ( BS_Writer_Open_filename( &hBsWriter, arg.outputBitstreamFilename, bsWriterFormat ) != IVAS_ERR_OK ) +#endif + { + fprintf( stderr, "\nCan't open %s\n\n", arg.outputBitstreamFilename ); + goto cleanup; + } + + /*------------------------------------------------------------------------------------------* + * Print out file names + *------------------------------------------------------------------------------------------*/ + + if ( arg.inputFormat == IVAS_ENC_INPUT_ISM || arg.inputFormat == IVAS_ENC_INPUT_SBA_ISM ) + { + for ( i = 0; i < arg.inputFormatConfig.ism.numObjects; i++ ) + { + fprintf( stdout, "Object %d input metadata: %s\n", i + 1, arg.inputFormatConfig.ism.metadataFiles[i] ); + } + } + + if ( arg.masaMetadataFile != NULL ) + { + fprintf( stdout, "MASA inp. metadata file: %s\n", arg.masaMetadataFile ); + } + + fprintf( stdout, "Input audio file: %s\n", arg.inputWavFilename ); + fprintf( stdout, "Output bitstream file: %s\n\n", arg.outputBitstreamFilename ); + + /*------------------------------------------------------------------------------------------* + * Open auxiliary input files + *------------------------------------------------------------------------------------------*/ + + int32_t totalBitrate = arg.initBitrate; + + if ( arg.bitrateProfileFile ) + { + if ( ( f_bitrateProfile = fopen( arg.bitrateProfileFile, "rb" ) ) == NULL ) + { + fprintf( stderr, "Error: bitrate profile file %s could not be opened\n\n", arg.bitrateProfileFile ); + usage_enc(); + goto cleanup; + } + + if ( !readBitrate( f_bitrateProfile, &totalBitrate ) ) + { + fprintf( stderr, "Error: bitrate profile file %s could not be read\n\n", arg.bitrateProfileFile ); + goto cleanup; + } + rewind( f_bitrateProfile ); + + fprintf( stdout, "Bitrate switching file: %s\n", arg.bitrateProfileFile ); + } + + int32_t bandwidthFrameCounter = 0; + IVAS_ENC_BANDWIDTH bandwidth = arg.maxBandwidth; + + if ( arg.bandwithProfileFile ) + { + if ( ( f_bwProfile = fopen( arg.bandwithProfileFile, "rb" ) ) == NULL ) + { + fprintf( stderr, "Error: incorrect bandwidth specification or the bandwidth profile file could not be opened: %s\n\n", arg.bandwithProfileFile ); + usage_enc(); + goto cleanup; + } + fprintf( stdout, "Bandwidth switching file: %s\n", arg.bandwithProfileFile ); + + if ( !readBandwidth( f_bwProfile, &bandwidth, &bandwidthFrameCounter ) ) + { + fprintf( stderr, "Error: bandwidth switching file %s could not be read\n\n", arg.bandwithProfileFile ); + goto cleanup; + } + rewind( f_bwProfile ); + bandwidthFrameCounter = 0; + } + else + { + if ( bandwidth == IVAS_ENC_BANDWIDTH_NB && arg.inputFormat != IVAS_ENC_INPUT_MONO ) + { + fprintf( stdout, "\nNB coding not supported in IVAS. Switching to WB.\n\n" ); + } + else + { + switch ( bandwidth ) + { + case IVAS_ENC_BANDWIDTH_UNDEFINED: + break; + case IVAS_ENC_BANDWIDTH_NB: + fprintf( stdout, "Max. encoded bandwidth: NB\n" ); + break; + case IVAS_ENC_BANDWIDTH_WB: + fprintf( stdout, "Max. encoded bandwidth: WB\n" ); + break; + case IVAS_ENC_BANDWIDTH_SWB: + fprintf( stdout, "Max. encoded bandwidth: SWB\n" ); + break; + case IVAS_ENC_BANDWIDTH_FB: + fprintf( stdout, "Max. encoded bandwidth: FB\n" ); + break; + default: + fprintf( stderr, "Error: Invalid bandwidth value\n" ); + usage_enc(); + goto cleanup; + } + } + } + + /*------------------------------------------------------------------------------------------* + * Handle Channel-aware mode + *------------------------------------------------------------------------------------------*/ + + IVAS_ENC_CHANNEL_AWARE_CONFIG caConfig = arg.caConfig; + + if ( arg.ca_config_file ) + { + if ( ( jbmReader = JbmFileReader_open( arg.ca_config_file ) ) == NULL ) + { + fprintf( stderr, "\nError: Channel aware configuration file could not be opened: %s\n\n", arg.ca_config_file ); + usage_enc(); + goto cleanup; + } + + fprintf( stdout, "Channel-aware mode: ON, config file: %s \n", arg.ca_config_file ); + } + else if ( caConfig.channelAwareModeEnabled ) + { + fprintf( stdout, "Channel-aware mode: ON, FEC indicator : %s FEC offset: %d \n\n", ( caConfig.fec_indicator == IVAS_ENC_FEC_LO ) ? "LO" : "HI", caConfig.fec_offset ); + } + + if ( arg.inputFormat != IVAS_ENC_INPUT_MONO && ( caConfig.channelAwareModeEnabled || arg.ca_config_file ) ) + { + fprintf( stderr, "Channel-aware mode is not supported in IVAS.\n\n" ); + usage_enc(); + goto cleanup; + } + + /*------------------------------------------------------------------------------------------* + * Configure and initialize (allocate memory for static variables) the encoder + *------------------------------------------------------------------------------------------*/ + + switch ( arg.inputFormat ) + { + case IVAS_ENC_INPUT_MONO: + if ( ( error = IVAS_ENC_ConfigureForMono( hIvasEnc, arg.inputFs, totalBitrate, arg.max_bwidth_user, bandwidth, arg.dtxConfig, caConfig, arg.inputFormatConfig.stereoToMonoDownmix, arg.is_binaural ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nIVAS_ENC_ConfigureForMono failed: %s\n\n", IVAS_ENC_GetErrorMessage( error ) ); + goto cleanup; + } + break; + case IVAS_ENC_INPUT_STEREO: +#ifdef DEBUGGING + if ( ( error = IVAS_ENC_ConfigureForStereo( hIvasEnc, arg.inputFs, totalBitrate, arg.max_bwidth_user, bandwidth, arg.dtxConfig, arg.is_binaural, arg.inputFormatConfig.stereoMode ) ) != IVAS_ERR_OK ) +#else + if ( ( error = IVAS_ENC_ConfigureForStereo( hIvasEnc, arg.inputFs, totalBitrate, arg.max_bwidth_user, bandwidth, arg.dtxConfig, arg.is_binaural ) ) != IVAS_ERR_OK ) +#endif + { + fprintf( stderr, "\nIVAS_ENC_ConfigureForStereo failed: %s\n\n", IVAS_ENC_GetErrorMessage( error ) ); + goto cleanup; + } + break; + case IVAS_ENC_INPUT_ISM: + if ( ( error = IVAS_ENC_ConfigureForObjects( hIvasEnc, arg.inputFs, totalBitrate, arg.max_bwidth_user, bandwidth, arg.dtxConfig, arg.inputFormatConfig.ism.numObjects, arg.ism_extended_metadata ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nIVAS_ENC_ConfigureForObjects failed: %s\n\n", IVAS_ENC_GetErrorMessage( error ) ); + goto cleanup; + } + break; + case IVAS_ENC_INPUT_SBA: + if ( ( error = IVAS_ENC_ConfigureForAmbisonics( hIvasEnc, arg.inputFs, totalBitrate, arg.max_bwidth_user, bandwidth, arg.dtxConfig, arg.inputFormatConfig.sba.order, arg.inputFormatConfig.sba.isPlanar, +#ifdef DEBUG_AGC_ENCODER_CMD_OPTION + arg.agc, +#endif + arg.pca +#ifdef DEBUG_SBA_AUDIO_DUMP + , + &numTransportChannels +#endif + ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nIVAS_ENC_ConfigureForAmbisonics failed: %s\n\n", IVAS_ENC_GetErrorMessage( error ) ); + goto cleanup; + } + + break; + case IVAS_ENC_INPUT_MASA: + if ( ( error = IVAS_ENC_ConfigureForMasa( hIvasEnc, arg.inputFs, totalBitrate, arg.max_bwidth_user, bandwidth, arg.dtxConfig, arg.inputFormatConfig.masaVariant ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nIVAS_ENC_ConfigureForMasa failed: %s\n\n", IVAS_ENC_GetErrorMessage( error ) ); + goto cleanup; + } + break; + case IVAS_ENC_INPUT_MC: + if ( ( error = IVAS_ENC_ConfigureForMultichannel( hIvasEnc, arg.inputFs, totalBitrate, arg.max_bwidth_user, bandwidth, arg.dtxConfig, arg.inputFormatConfig.mcLayout ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nIVAS_ENC_ConfigureForMultichannel failed: %s\n\n", IVAS_ENC_GetErrorMessage( error ) ); + goto cleanup; + } + break; + case IVAS_ENC_INPUT_SBA_ISM: + if ( ( error = IVAS_ENC_ConfigureForSBAObjects( hIvasEnc, arg.inputFs, totalBitrate, bandwidth, arg.dtxConfig, arg.inputFormatConfig.sba_ism.numObjects, arg.inputFormatConfig.sba_ism.order, arg.inputFormatConfig.sba_ism.isPlanar, arg.pca ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nIVAS_ENC_ConfigureForSBAObjects failed: %s\n\n", IVAS_ENC_GetErrorMessage( error ) ); + goto cleanup; + } + break; + 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 ) ); + goto cleanup; + } + break; + default: + fprintf( stderr, "\nInvalid input type\n\n" ); + goto cleanup; + } + + if ( ( error = IVAS_ENC_PrintConfig( hIvasEnc, caConfig.channelAwareModeEnabled ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\n IVAS_ENC_PrintConfig failed %s\n\n", IVAS_ENC_GetErrorMessage( error ) ); + goto cleanup; + } + + /*------------------------------------------------------------------------------------------* + * Open input audio file + *------------------------------------------------------------------------------------------*/ + + if ( AudioFileReader_open( &audioReader, arg.inputWavFilename ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nCan't open %s\n\n", arg.inputWavFilename ); + goto cleanup; + } + + /* Validate input sampling rate */ + int32_t inFileSampleRate = 0; + error = AudioFileReader_getSamplingRate( audioReader, &inFileSampleRate ); + switch ( error ) + { + case IVAS_ERR_OK: + if ( inFileSampleRate != arg.inputFs ) + { + fprintf( stderr, "\nSampling rate mismatch: %d Hz requested, but %d Hz found in file %s\n\n", arg.inputFs, inFileSampleRate, arg.inputWavFilename ); + goto cleanup; + } + break; + case IVAS_ERR_SAMPLING_RATE_UNKNOWN: + /* IVAS_ERR_SAMPLING_RATE_UNKNOWN will be returned for raw PCM files. + * Nothing to check here */ + break; + default: + fprintf( stderr, "\nError: %s\n", ivas_error_to_string( error ) ); + goto cleanup; + } + + /* Validate number of channels */ + int16_t encInNumChannels = 0; + if ( ( error = IVAS_ENC_GetNumInChannels( hIvasEnc, &encInNumChannels ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError: %s\n", ivas_error_to_string( error ) ); + goto cleanup; + } + + int16_t inFileNumChannels = 0; + error = AudioFileReader_getNumChannels( audioReader, &inFileNumChannels ); + switch ( error ) + { + case IVAS_ERR_OK: + if ( inFileNumChannels != encInNumChannels ) + { + fprintf( stderr, "\nNumber of input audio channels mismatch: %d accepted by encoder, but %d found in file %s\n\n", encInNumChannels, inFileNumChannels, arg.inputWavFilename ); + goto cleanup; + } + break; + case IVAS_ERR_NUM_CHANNELS_UNKNOWN: + /* IVAS_ERR_NUM_CHANNELS_UNKNOWN will be returned for raw PCM files. + * Nothing to check here */ + break; + default: + fprintf( stderr, "\nError: %s\n", ivas_error_to_string( error ) ); + goto cleanup; + } + + /*------------------------------------------------------------------------------------------* + * Open input metadata files + *------------------------------------------------------------------------------------------*/ + + if ( arg.masaMetadataFile ) + { + if ( ( masaReader = MasaFileReader_open( arg.masaMetadataFile ) ) == NULL ) + { + fprintf( stderr, "\nError: MASA input metadata file %s could not be opened\n\n", arg.masaMetadataFile ); + usage_enc(); + goto cleanup; + } + } + + const int16_t numIsmInputs = ( arg.inputFormat == IVAS_ENC_INPUT_ISM || arg.inputFormat == IVAS_ENC_INPUT_MASA_ISM || arg.inputFormat == IVAS_ENC_INPUT_SBA_ISM ) ? arg.inputFormatConfig.ism.numObjects : 0; + + for ( i = 0; i < numIsmInputs; ++i ) + { + if ( arg.inputFormatConfig.ism.metadataFiles[i] != NULL ) + { + if ( ( ismReaders[i] = IsmFileReader_open( arg.inputFormatConfig.ism.metadataFiles[i] ) ) == NULL ) + { + fprintf( stderr, "\nError: ISM input metadata file %s could not be opened\n\n", arg.inputFormatConfig.ism.metadataFiles[i] ); + usage_enc(); + goto cleanup; + } + } + } + +#ifdef DEBUGGING + IVAS_ENC_FORCED_MODE forcedMode = arg.forcedMode; + int32_t force_profile_cnt = 0; + + if ( arg.forcedModeFile ) + { + if ( ( f_forcedModeProfile = fopen( arg.forcedModeFile, "rb" ) ) == NULL ) + { + fprintf( stderr, "\nError: Incorrect mode specification or the profile file could not be opened: %s\n\n", arg.forcedModeFile ); + usage_enc(); + goto cleanup; + } + } +#endif + + /*------------------------------------------------------------------------------------------* + * Allocate input data buffer + *------------------------------------------------------------------------------------------*/ + + int16_t pcmBufSize; + if ( ( error = IVAS_ENC_GetInputBufferSize( hIvasEnc, &pcmBufSize ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nGetInputBufferSize failed: %s\n\n", IVAS_ENC_GetErrorMessage( error ) ); + goto cleanup; + } + + pcmBuf = malloc( pcmBufSize * sizeof( int16_t ) ); + + /*------------------------------------------------------------------------------------------* + * Compensate for encoder delay (bitstream aligned with input signal) + *------------------------------------------------------------------------------------------*/ + + int16_t encDelayInSamples; + if ( ( error = IVAS_ENC_GetDelay( hIvasEnc, &encDelayInSamples ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nGetDelay failed: %s\n\n", IVAS_ENC_GetErrorMessage( error ) ); + goto cleanup; + } + + if ( arg.delayCompensationEnabled && encDelayInSamples ) + { + /* read samples and throw them away */ + int16_t numSamplesRead = 0; + if ( ( error = AudioFileReader_read( audioReader, pcmBuf, encDelayInSamples, &numSamplesRead ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError reading from file %s\n%s\n", arg.inputWavFilename, IVAS_ENC_GetErrorMessage( error ) ); + goto cleanup; + } + } + +#ifdef IVAS_RTPDUMP + /*------------------------------------------------------------------------------------------* + * RTPDump + *------------------------------------------------------------------------------------------*/ + + if ( arg.rtpdumpOutput && init_RtpWriter ) + { +#ifdef FIXED_RTP_SEQUENCE_NUM + if ( ( error = IVAS_RTP_WRITER_Init( ivasRtp, arg.outputBitstreamFilename, arg.numFramesPerPacket, ssrc, seqNumInitVal ) ) != IVAS_ERR_OK ) +#else + if ( ( error = IVAS_RTP_WRITER_Init( ivasRtp, arg.outputBitstreamFilename, arg.numFramesPerPacket ) ) != IVAS_ERR_OK ) +#endif + { + fprintf( stderr, "\nError: Can't open output bitstream file for RTP output %s \n\n", arg.outputBitstreamFilename ); + goto cleanup; + } + } + + /*------------------------------------------------------------------------------------------* + * Open scene orientation file + *------------------------------------------------------------------------------------------*/ + + if ( arg.sceneOrientationTrajFileName != NULL ) + { + if ( ( error = RotationFileReader_open( arg.sceneOrientationTrajFileName, &sceneOrientationFileReader ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError: Can't open scene orientation file %s \n\n", arg.sceneOrientationTrajFileName ); + goto cleanup; + } + } + + /*------------------------------------------------------------------------------------------* + * Open device orientation file + *------------------------------------------------------------------------------------------*/ + + if ( arg.deviceOrientationTrajFileName != NULL ) + { + if ( ( error = RotationFileReader_open( arg.deviceOrientationTrajFileName, &deviceOrientationFileReader ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError: Can't open device orientation file %s \n\n", arg.deviceOrientationTrajFileName ); + goto cleanup; + } + } +#endif + + /*------------------------------------------------------------------------------------------* + * Run the encoder + *------------------------------------------------------------------------------------------*/ + + int16_t numSamplesRead = 0; + uint16_t bitStream[IVAS_MAX_BITS_PER_FRAME]; + uint16_t numBits = 0; +#ifdef DEBUG_SBA +#ifdef DEBUG_AGC + ivas_open_agc_debug_files( (int16_t) arg.agc ); +#endif + ivas_open_sba_encoder_debug_files( arg.inputFs, numTransportChannels, arg.dbg_file_tag, arg.initBitrate, (int16_t) arg.dtxConfig.enabled ); +#endif + + if ( !arg.quietModeEnabled ) + { + fprintf( stdout, "\n------ Running the encoder ------\n\n" ); + fprintf( stdout, "Frames processed: " ); + } + else + { + fprintf( stdout, "\n\n-- Start the encoder (quiet mode) --\n\n" ); + } + +#ifdef WMOPS + reset_stack(); + reset_wmops(); +#endif + + /*------------------------------------------------------------------------------------------* + * Loop for every frame of input data + * - Read the input data + * - Process switching files + * - Read input metadata + * - Run the encoder + * - Write the parameters into output bitstream file + *------------------------------------------------------------------------------------------*/ + + while ( 1 ) + { + /* Read the input data */ + if ( ( error = AudioFileReader_read( audioReader, pcmBuf, pcmBufSize, &numSamplesRead ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError reading from file %s\n%s\n", arg.inputWavFilename, IVAS_ENC_GetErrorMessage( error ) ); + goto cleanup; + } + + if ( numSamplesRead == 0 ) + { + /* end of input data */ + break; + } + + /* Zero-pad if not enough samples were read (expected in last frame) */ + if ( numSamplesRead < pcmBufSize ) + { + for ( i = numSamplesRead; i < pcmBufSize; ++i ) + { + pcmBuf[i] = 0; + } + } + + /* Process switching files */ + if ( f_bitrateProfile ) + { + if ( !readBitrate( f_bitrateProfile, &totalBitrate ) ) + { + fprintf( stderr, "Error: bitrate profile file %s could not be read\n\n", arg.bitrateProfileFile ); + goto cleanup; + } + + if ( ( error = IVAS_ENC_SetBitrate( hIvasEnc, totalBitrate ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nIVAS_ENC_SetBitrate failed: %s\n\n", IVAS_ENC_GetErrorMessage( error ) ); + goto cleanup; + } + } + + if ( f_bwProfile ) + { + if ( !readBandwidth( f_bwProfile, &bandwidth, &bandwidthFrameCounter ) ) + { + fprintf( stderr, "Error: bandwidth switching file %s could not be read\n\n", arg.bandwithProfileFile ); + goto cleanup; + } + + if ( ( error = IVAS_ENC_SetBandwidth( hIvasEnc, bandwidth ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nIVAS_ENC_SetBandwidth failed: %s\n\n", IVAS_ENC_GetErrorMessage( error ) ); + goto cleanup; + } + } + + if ( jbmReader ) + { + if ( ( error = JbmFileReader_readCAconfig( jbmReader, &caConfig ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError (%s) while reading Channel-Aware Config. from: %s\n\n", IVAS_ENC_GetErrorMessage( error ), JbmFileReader_getFilePath( jbmReader ) ); + goto cleanup; + } + + if ( ( error = IVAS_ENC_SetChannelAwareConfig( hIvasEnc, caConfig ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "IVAS_ENC_SetChannelAwareConfig failed: %s\n\n", IVAS_ENC_GetErrorMessage( error ) ); + goto cleanup; + } + } + +#ifdef DEBUGGING + if ( f_forcedModeProfile ) + { + if ( ( error = readForcedMode( f_forcedModeProfile, &forcedMode, &force_profile_cnt ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError reading from file: %s\n%s\n", arg.forcedModeFile, IVAS_ENC_GetErrorMessage( error ) ); + goto cleanup; + } + } + + /* Force mode not set when configuring, set in first frame even if not reading from file */ + if ( f_forcedModeProfile || frame == 0 ) + { + if ( ( error = IVAS_ENC_SetForcedMode( hIvasEnc, forcedMode ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nIVAS_ENC_SetForcedMode failed: %s\n\n", IVAS_ENC_GetErrorMessage( error ) ); + goto cleanup; + } + } +#endif + /* Read ISM input metadata */ + for ( i = 0; i < numIsmInputs; ++i ) + { + if ( ismReaders[i] == NULL ) + { + continue; + } + + IVAS_ISM_METADATA ismMetadata; + if ( ( error = IsmFileReader_readNextFrame( ismReaders[i], &ismMetadata ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError (%s) while reading ism metadata from: %s\n\n", IVAS_ENC_GetErrorMessage( error ), IsmFileReader_getFilePath( ismReaders[i] ) ); + goto cleanup; + } + + if ( ( error = IVAS_ENC_FeedObjectMetadata( hIvasEnc, i, ismMetadata ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nfeed_ISM_metadata failed: %s\n\n", IVAS_ENC_GetErrorMessage( error ) ); + goto cleanup; + } + } + + /* Read MASA input metadata */ + if ( masaReader ) + { + if ( ( error = MasaFileReader_readNextFrame( masaReader ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError (%s) while reading masa metadata from: %s\n\n", IVAS_ENC_GetErrorMessage( error ), arg.masaMetadataFile ); + goto cleanup; + } + IVAS_MASA_METADATA_HANDLE hMetadata = MasaFileReader_getMetadataHandle( masaReader ); + + if ( ( error = IVAS_ENC_FeedMasaMetadata( hIvasEnc, hMetadata ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nfeed_MASA_frame failed: %s\n\n", IVAS_ENC_GetErrorMessage( error ) ); + goto cleanup; + } + } + + /* *** Encode one frame *** */ +#ifdef IVAS_RTPDUMP + if ( ivasRtp->hPack ) + { + bool isMono = ( arg.inputFormat == IVAS_ENC_INPUT_MONO ); + bool forcePacket = ( numSamplesRead < pcmBufSize ); /* If EoF force Packet generation */ + + ivasRtp->nWrittenPiData = 0; + + /* scene orientation */ + if ( sceneOrientationFileReader ) + { + PIDATA_TS *piDataTs = &ivasRtp->piData[ivasRtp->nWrittenPiData++]; + IVAS_PIDATA_ORIENTATION *scene = &piDataTs->data.scene; + + memset( piDataTs, 0, sizeof( PIDATA_TS ) ); + scene->size = sizeof( IVAS_PIDATA_ORIENTATION ); + scene->piDataType = IVAS_PI_SCENE_ORIENTATION; + + if ( ( error = HeadRotationFileReading( sceneOrientationFileReader, &scene->orientation, NULL ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError %s while reading scene orientation from %s\n", IVAS_ENC_GetErrorMessage( error ), RotationFileReader_getFilePath( sceneOrientationFileReader ) ); + goto cleanup; + } + } + + /* device orientation */ + if ( deviceOrientationFileReader ) + { + PIDATA_TS *piDataTs = &ivasRtp->piData[ivasRtp->nWrittenPiData++]; + IVAS_PIDATA_ORIENTATION *device = &piDataTs->data.deviceUnCompensated; + + memset( piDataTs, 0, sizeof( PIDATA_TS ) ); + device->size = sizeof( IVAS_PIDATA_ORIENTATION ); + device->piDataType = IVAS_PI_DEVICE_ORIENTATION_COMPENSATED; + + if ( ( error = HeadRotationFileReading( deviceOrientationFileReader, &device->orientation, NULL ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError %s while reading device orientation from %s\n", IVAS_ENC_GetErrorMessage( error ), RotationFileReader_getFilePath( deviceOrientationFileReader ) ); + goto cleanup; + } + } + + if ( ( error = IVAS_ENC_EncodeFrameToCompact( hIvasEnc, pcmBuf, pcmBufSize, au, &numBits ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nencodeFrame failed: %s\n\n", IVAS_ENC_GetErrorMessage( error ) ); + goto cleanup; + } + +#ifdef RTP_S4_251135_CR26253_0016_REV1 + if ( ( error = IVAS_RTP_WriteNextFrame( ivasRtp, au, NULL, numBits, isMono, forcePacket ) ) != IVAS_ERR_OK ) +#else + if ( ( error = IVAS_RTP_WriteNextFrame( ivasRtp, au, numBits, isMono, forcePacket ) ) != IVAS_ERR_OK ) +#endif + { + fprintf( stderr, "\nError %s while pushing audio frame to RTP pack\n", IVAS_ENC_GetErrorMessage( error ) ); + goto cleanup; + } + } + else + { +#endif + if ( ( error = IVAS_ENC_EncodeFrameToSerial( hIvasEnc, pcmBuf, pcmBufSize, bitStream, &numBits ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nencodeFrame failed: %s\n\n", IVAS_ENC_GetErrorMessage( error ) ); + goto cleanup; + } + + /* write bitstream */ + if ( ( error = BS_Writer_WriteFrame_short( hBsWriter, bitStream, numBits, totalBitrate ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nBS_Writer_WriteFrame_short failed, error code %d\n\n", error ); + goto cleanup; + } +#ifdef IVAS_RTPDUMP + } +#endif + + frame++; + if ( !arg.quietModeEnabled ) + { + fprintf( stdout, "%-8d\b\b\b\b\b\b\b\b", frame ); + } + +#ifdef WMOPS + update_mem(); + update_wmops(); +#endif + } + + if ( arg.quietModeEnabled ) + { + fprintf( stdout, "Encoding finished\n" ); + } + else + { + fprintf( stdout, "\n\nEncoding of %d frames finished\n", frame ); + } + +#ifdef DEBUGGING + if ( ( noClipping = IVAS_ENC_GetNoCLipping( hIvasEnc, &maxOverload, &minOverload ) ) > 0 ) + { + fprintf( stdout, "Core input overload detected: %d samples!!!\n", noClipping ); + fprintf( stdout, "Max overload value: %f \n", maxOverload ); + fprintf( stdout, "Min overload value: %f \n\n", minOverload ); + } + print_snr(); +#endif + /*------------------------------------------------------------------------------------------* + * Close files and deallocate resources + *------------------------------------------------------------------------------------------*/ + + mainFailed = false; /* This will stay set to true if cleanup is reached via a goto due to an error */ + +cleanup: + + free( pcmBuf ); + + if ( ( error = BS_Writer_Close( &hBsWriter ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Can't close bitstream writer, error code %d\n", error ); + mainFailed = true; + } + + AudioFileReader_close( &audioReader ); + + if ( jbmReader ) + { + JbmFileReader_close( &jbmReader ); + } + + for ( i = 0; i < IVAS_MAX_NUM_OBJECTS; ++i ) + { + if ( ismReaders[i] != NULL ) + { + IsmFileReader_close( &ismReaders[i] ); + } + } + + if ( masaReader ) + { + MasaFileReader_close( &masaReader ); + } + + if ( f_bwProfile ) + { + fclose( f_bwProfile ); + } + + if ( f_bitrateProfile ) + { + fclose( f_bitrateProfile ); + } + +#ifdef IVAS_RTPDUMP + if ( sceneOrientationFileReader ) + { + RotationFileReader_close( &sceneOrientationFileReader ); + } + + if ( deviceOrientationFileReader ) + { + RotationFileReader_close( &deviceOrientationFileReader ); + } + + /* IVAS_RTP_Term( &ivasRtp ); */ +#endif + + IVAS_ENC_Close( &hIvasEnc ); + +#ifdef WMOPS + print_wmops(); + print_mem( NULL ); +#endif +#ifdef DEBUGGING + dbgclose(); + + if ( f_forcedModeProfile ) + { + fclose( f_forcedModeProfile ); + } + +#ifdef DEBUG_SBA + ivas_close_sba_encoder_debug_files(); +#ifdef DEBUG_AGC + ivas_close_agc_debug_files(); +#endif +#endif +#endif + + return mainFailed ? -1 : 0; +} + +/*---------------------------------------------------------------------* + * parseCmdlIVAS_enc() + * + * Encoder command-line parsing + *---------------------------------------------------------------------*/ + +static bool parseCmdlIVAS_enc( + int16_t argc, + char *argv[], + EncArguments *arg ) +{ + int16_t i, j; + char argv_to_upper[FILENAME_MAX]; + char stmp[FILENAME_MAX]; + int32_t tmp; + + /*-----------------------------------------------------------------* + * Set default values + *-----------------------------------------------------------------*/ + + arg->inputWavFilename = NULL; + arg->outputBitstreamFilename = NULL; + arg->inputFs = IVAS_MAX_SAMPLING_RATE; + arg->inputFormat = IVAS_ENC_INPUT_MONO; + arg->is_binaural = false; + arg->inputFormatConfig.stereoToMonoDownmix = false; + arg->max_bwidth_user = false; + arg->maxBandwidth = IVAS_ENC_BANDWIDTH_UNDEFINED; + arg->bandwithProfileFile = NULL; + arg->dtxConfig = IVAS_ENC_GetDefaultDtxConfig(); + arg->initBitrate = 0; + arg->bitrateProfileFile = NULL; + arg->quietModeEnabled = false; + arg->delayCompensationEnabled = true; + arg->masaMetadataFile = NULL; + arg->caConfig = IVAS_ENC_GetDefaultChannelAwareConfig(); + arg->ca_config_file = NULL; + arg->mimeOutput = false; + arg->ism_extended_metadata = false; + arg->complexityLevel = IVAS_ENC_COMPLEXITY_LEVEL_THREE; +#ifdef IVAS_RTPDUMP + arg->rtpdumpOutput = false; + arg->sceneOrientationTrajFileName = NULL; + arg->deviceOrientationTrajFileName = NULL; +#endif + +#ifdef DEBUGGING + arg->forcedMode = IVAS_ENC_FORCE_UNFORCED; + arg->forcedModeFile = NULL; +#ifdef DEBUG_AGC_ENCODER_CMD_OPTION + arg->agc = IVAS_ENC_AGC_UNDEFINED; +#endif +#ifdef DEBUG_FOA_AGC + arg->agcBitstream = NULL; +#endif +#ifdef DEBUG_SBA + arg->dbg_file_tag = NULL; +#endif +#endif + arg->pca = false; + + /*-----------------------------------------------------------------* + * Initialization + *-----------------------------------------------------------------*/ + + if ( argc < 5 ) + { + fprintf( stderr, "Error: Not enough input parameters. Exiting!\n\n" ); + usage_enc(); + return false; + } + + /*-----------------------------------------------------------------* + * Optional input arguments + *-----------------------------------------------------------------*/ + + i = 1; + while ( i < argc - 4 ) + { + strncpy( argv_to_upper, argv[i], sizeof( argv_to_upper ) - 1 ); + argv_to_upper[sizeof( argv_to_upper ) - 1] = '\0'; + to_upper( argv_to_upper ); + + /*-----------------------------------------------------------------* + * Bandwidth limitation + *-----------------------------------------------------------------*/ + + if ( strcmp( argv_to_upper, "-MAX_BAND" ) == 0 ) + { + arg->max_bwidth_user = true; + + strncpy( stmp, argv[i + 1], sizeof( stmp ) - 1 ); + stmp[sizeof( stmp ) - 1] = '\0'; + to_upper( stmp ); + + if ( strcmp( stmp, "-NB" ) == 0 || strcmp( stmp, "NB" ) == 0 ) + { + arg->maxBandwidth = IVAS_ENC_BANDWIDTH_NB; + } + else if ( strcmp( stmp, "-WB" ) == 0 || strcmp( stmp, "WB" ) == 0 ) + { + arg->maxBandwidth = IVAS_ENC_BANDWIDTH_WB; + } + else if ( strcmp( stmp, "-SWB" ) == 0 || strcmp( stmp, "SWB" ) == 0 ) + { + arg->maxBandwidth = IVAS_ENC_BANDWIDTH_SWB; + } + else if ( strcmp( stmp, "-FB" ) == 0 || strcmp( stmp, "FB" ) == 0 ) + { + arg->maxBandwidth = IVAS_ENC_BANDWIDTH_FB; + } + else + { + arg->bandwithProfileFile = argv[i + 1]; + } + + i += 2; + } + + /*-----------------------------------------------------------------* + * Quiet mode + *-----------------------------------------------------------------*/ + + else if ( strcmp( argv_to_upper, "-Q" ) == 0 ) + { + i++; + arg->quietModeEnabled = true; + } + + /*-----------------------------------------------------------------* + * DTX/CNG + *-----------------------------------------------------------------*/ + + else if ( strcmp( argv_to_upper, "-DTX" ) == 0 ) + { + i++; + if ( i < argc - 4 ) + { + if ( sscanf( argv[i], "%d", &tmp ) <= 0 ) + { + tmp = DEFAULT_FIXED_SID_RATE; + } + else + { + i++; + } + } + else + { + tmp = DEFAULT_FIXED_SID_RATE; + } + + arg->dtxConfig.enabled = true; + + if ( tmp == 0 ) + { + arg->dtxConfig.variable_SID_rate = true; + arg->dtxConfig.SID_interval = 0; + } + else if ( tmp >= 3 && tmp <= 100 ) + { + arg->dtxConfig.variable_SID_rate = false; + arg->dtxConfig.SID_interval = (int16_t) tmp; + } + else + { + fprintf( stderr, "Error: Incorrect SID update interval specified: %d (supported 3-100)\n\n", tmp ); + usage_enc(); + return false; + } + } + +#ifdef DEBUGGING + /*-----------------------------------------------------------------* + * Force specific mode + *-----------------------------------------------------------------*/ + + else if ( strcmp( argv_to_upper, "-FORCE" ) == 0 ) + { + strncpy( stmp, argv[i + 1], sizeof( stmp ) ); + + arg->forcedMode = parseForcedMode( stmp ); + + if ( arg->forcedMode == IVAS_ENC_FORCE_UNDEFINED ) + { + arg->forcedModeFile = argv[i + 1]; + fprintf( stdout, "Force switching file: %s\n", argv[i + 1] ); + } + else + { + fprintf( stdout, "Forcing codec to: %s\n", argv[i + 1] ); + } + + i += 2; + } +#ifdef DEBUG_MODE_INFO +#ifdef DEBUG_MODE_INFO_TWEAK + /*-----------------------------------------------------------------* + * Define additional subfolder for debug info output in ./res + *-----------------------------------------------------------------*/ + else if ( strcmp( argv_to_upper, "-INFO" ) == 0 ) + { + extern char infoFolder[FILENAME_MAX]; + strncpy( infoFolder, argv[i + 1], sizeof( infoFolder ) ); + i += 2; + } +#endif /* #ifdef DEBUG_MODE_INFO_TWEAK */ +#endif /* #ifdef DEBUG_MODE_INFO */ + +#ifdef DEBUG_AGC_ENCODER_CMD_OPTION + /*-----------------------------------------------------------------* + * IVAS SPAR AGC option + *-----------------------------------------------------------------*/ + else if ( strcmp( argv_to_upper, "-AGC" ) == 0 ) + { + i++; + if ( i < argc - 4 ) + { + arg->agc = ( atoi( argv[i] ) ) ? IVAS_ENC_AGC_ENABLED : IVAS_ENC_AGC_DISABLED; + if ( argv[i] == NULL || atoi( argv[i] ) < 0 || atoi( argv[i] ) > 1 ) + { + fprintf( stderr, "Error: wrong adaptive gain control option specified (%d), expected 0 or 1\n\n", (int32_t) atoi( argv[i] ) ); + usage_enc(); + return false; + } + i++; + } + else + { + fprintf( stderr, "Error: unspecified adaptive gain control option\n\n" ); + usage_enc(); + return false; + } + } +#endif + +#ifdef DEBUG_SBA + /*-----------------------------------------------------------------* + * IVAS SPAR debug files tag + *-----------------------------------------------------------------*/ + else if ( strcmp( argv_to_upper, "-TAG" ) == 0 ) + { + i++; + if ( i < argc - 4 ) + { + arg->dbg_file_tag = argv[i]; + ++i; + } + else + { + fprintf( stderr, "Error: [IVAS SPAR Encoder] unspecified tag value \n\n" ); + usage_enc(); + return false; + } + } +#endif +#endif /* #ifdef DEBUGGING */ + + /*-----------------------------------------------------------------* + * deactivate delay compensation + *-----------------------------------------------------------------*/ + + else if ( strcmp( argv_to_upper, "-NO_DELAY_CMP" ) == 0 ) + { + arg->delayCompensationEnabled = false; + i++; + } + + /*-----------------------------------------------------------------* + * Activate channel-aware mode + *-----------------------------------------------------------------*/ + + else if ( strcmp( argv_to_upper, "-RF" ) == 0 ) + { + arg->caConfig.channelAwareModeEnabled = 1; + i++; + + if ( i < argc - 4 ) + { + strncpy( stmp, argv[i], sizeof( stmp ) ); + stmp[sizeof( stmp ) - 1] = '\0'; + to_upper( stmp ); + if ( strcmp( stmp, "LO" ) == 0 ) + { + arg->caConfig.fec_indicator = IVAS_ENC_FEC_LO; + } + else if ( strcmp( stmp, "HI" ) == 0 ) + { + arg->caConfig.fec_indicator = IVAS_ENC_FEC_HI; + } + else + { + arg->ca_config_file = argv[i]; + } + i++; + + if ( ( sscanf( argv[i], "%d", &tmp ) == 1 ) && ( i < argc - 4 ) ) + { + if ( tmp == 0 ) + { + arg->caConfig.channelAwareModeEnabled = 0; + arg->caConfig.fec_offset = 0; + i++; + } + else + { + arg->caConfig.fec_offset = (int16_t) tmp; + i++; + } + } + } + else + { + arg->caConfig.fec_indicator = IVAS_ENC_FEC_HI; + } + } + + /*-----------------------------------------------------------------* + * MIME output file format + *-----------------------------------------------------------------*/ + + else if ( strcmp( argv_to_upper, "-MIME" ) == 0 ) + { + arg->mimeOutput = true; + fprintf( stdout, "Output bitstream file format: MIME\n" ); + ++i; + } + + + /*-----------------------------------------------------------------* + * Complexity Level + *-----------------------------------------------------------------*/ + + /* actual parsing of level will be implemented after characterization */ + else if ( strcmp( argv_to_upper, "-LEVEL" ) == 0 ) + { + int16_t level; + + ++i; + level = (int16_t) atoi( argv[i++] ); + if ( level < IVAS_ENC_COMPLEXITY_LEVEL_ONE || level > IVAS_ENC_COMPLEXITY_LEVEL_THREE ) + { + fprintf( stdout, "Invalid complexity level specified.\n" ); + usage_enc(); + return false; + } + else if ( level == IVAS_ENC_COMPLEXITY_LEVEL_ONE || level == IVAS_ENC_COMPLEXITY_LEVEL_TWO ) + { + fprintf( stdout, "Complexity levels 1 and 2 will be defined after characterisation - default to level 3 (full functionality).\n" ); + } + } + + /*-----------------------------------------------------------------* + * IVAS Formats + *-----------------------------------------------------------------*/ + + else if ( strcmp( argv_to_upper, "-STEREO" ) == 0 ) + { + i++; + arg->inputFormat = IVAS_ENC_INPUT_STEREO; + +#ifdef DEBUGGING + if ( ( i < argc - 4 ) && argv[i][0] != 45 ) /* note: 45 corresponds to "-" */ + { + if ( sscanf( argv[i], "%d", &tmp ) > 0 ) + { + if ( tmp == 1 ) + { + arg->inputFormatConfig.stereoMode = IVAS_ENC_STEREO_MODE_DFT; + i++; + } + else if ( tmp == 2 ) + { + arg->inputFormatConfig.stereoMode = IVAS_ENC_STEREO_MODE_TD; + i++; + } + else if ( tmp == 3 ) + { + arg->inputFormatConfig.stereoMode = IVAS_ENC_STEREO_MODE_MDCT_DECISION; +#ifdef DEBUG_FORCE_MDCT_STEREO_MODE + i++; + + /* force mdct stereo mode for debugging purposes */ + if ( i < argc - 4 ) + { + if ( sscanf( argv[i], "%d", &tmp ) > 0 ) + { + if ( tmp == 0 ) + { + /* keep "DECISION" */ + arg->inputFormatConfig.stereoMode = IVAS_ENC_STEREO_MODE_MDCT_DECISION; + i++; + } + else if ( tmp == 1 ) + { + arg->inputFormatConfig.stereoMode = IVAS_ENC_STEREO_MODE_MDCT_FORCE_LR; + i++; + } + else if ( tmp == 2 ) + { + arg->inputFormatConfig.stereoMode = IVAS_ENC_STEREO_MODE_MDCT_FORCE_MS; + i++; + } + else + { + fprintf( stderr, "Error: Incorrect mdct stereo coding method (%d) specified\n\n", tmp ); + usage_enc(); + return false; + } + } + } +#endif + } + else + { + fprintf( stderr, "Error: Incorrect stereo mode (%d) specified\n\n", tmp ); + usage_enc(); + return false; + } + } + else + { + fprintf( stderr, "Error: Stereo mode not specified.\n\n" ); /* in the debugging stage */ + usage_enc(); + return false; + } + } + else + { + arg->inputFormatConfig.stereoMode = IVAS_ENC_STEREO_MODE_UNIFIED; + } +#endif /* DEBUGGING */ + } + else if ( strcmp( argv_to_upper, "-BINAURAL" ) == 0 ) + { + arg->is_binaural = true; + i++; + } + else if ( strcmp( argv_to_upper, "-ISM" ) == 0 ) + { + arg->inputFormat = IVAS_ENC_INPUT_ISM; + i++; + + if ( i < argc - 4 ) + { + if ( argv[i][0] == '+' ) + { + argv[i]++; + arg->ism_extended_metadata = true; + } + if ( !is_digits_only( argv[i] ) ) + { + fprintf( stderr, "Error: Number of ISM channels must be an integer number!\n\n" ); + usage_enc(); + return false; + } + + if ( sscanf( argv[i], "%d", &tmp ) > 0 ) + { + i++; + } + + if ( tmp <= 0 ) + { + fprintf( stderr, "Error: Too low number of ISM channels specified!\n\n" ); + usage_enc(); + return false; + } + else if ( tmp > IVAS_MAX_NUM_OBJECTS ) + { + fprintf( stderr, "Error: Too high number of ISM channels specified!\n\n" ); + usage_enc(); + return false; + } + else + { + arg->inputFormatConfig.ism.numObjects = (int16_t) tmp; + } + } + else + { + fprintf( stderr, "Error: Number of ISM channels not specified!\n\n" ); + usage_enc(); + return false; + } + + /* read input metadata files */ + for ( j = 0; j < arg->inputFormatConfig.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.ism.metadataFiles[j] = NULL; + } + else + { + arg->inputFormatConfig.ism.metadataFiles[j] = argv[i]; + } + + i++; + } + else + { + fprintf( stderr, "Error: not enough metadata arguments specified!\n\n" ); + usage_enc(); + return false; + } + } + } + else if ( strcmp( argv_to_upper, "-SBA" ) == 0 ) + { + i++; + arg->inputFormat = IVAS_ENC_INPUT_SBA; + + /* SBA configuration */ + if ( i < argc - 4 && is_number( argv[i] ) && sscanf( argv[i], "%d", &tmp ) > 0 ) + { + i++; + } + else + { + tmp = -1; /* this is to avoid a compilation warning */ + fprintf( stderr, "Error: SBA order must be specified, expecting a number!\n\n" ); + usage_enc(); + return false; + } + + arg->inputFormatConfig.sba.isPlanar = ( tmp < 0 ); + + tmp = abs( tmp ); + switch ( tmp ) + { + case 1: + arg->inputFormatConfig.sba.order = IVAS_ENC_SBA_FOA; + break; + case 2: + arg->inputFormatConfig.sba.order = IVAS_ENC_SBA_HOA2; + break; + case 3: + arg->inputFormatConfig.sba.order = IVAS_ENC_SBA_HOA3; + break; + default: + fprintf( stderr, "Error: Wrong SBA order specified!\n\n" ); + usage_enc(); + return false; + } + } + else if ( strcmp( argv_to_upper, "-MASA" ) == 0 ) + { + arg->inputFormat = IVAS_ENC_INPUT_MASA; + i++; + + if ( i < argc - 4 ) + { + if ( !is_digits_only( argv[i] ) ) + { + fprintf( stderr, "Error: Number of MASA channels must be an integer number!\n\n" ); + usage_enc(); + return false; + } + + if ( sscanf( argv[i], "%d", &tmp ) > 0 ) + { + i++; + } + + switch ( tmp ) + { + case 1: + arg->inputFormatConfig.masaVariant = IVAS_ENC_MASA_1CH; + break; + case 2: + arg->inputFormatConfig.masaVariant = IVAS_ENC_MASA_2CH; + break; + default: + fprintf( stderr, "Error: MASA channels must be 1 or 2.\n\n" ); + usage_enc(); + return false; + } + } + + if ( i < argc - 4 ) + { + arg->masaMetadataFile = argv[i]; + i++; + } + else + { + fprintf( stderr, "Error: not enough MASA arguments\n\n" ); + usage_enc(); + return false; + } + } + else if ( strcmp( argv_to_upper, "-MC" ) == 0 ) + { + i++; + arg->inputFormat = IVAS_ENC_INPUT_MC; + + if ( i < argc - 4 ) + { + if ( strcmp( argv[i], "5_1" ) == 0 ) + { + arg->inputFormatConfig.mcLayout = IVAS_ENC_MC_5_1; + } + else if ( strcmp( argv[i], "7_1" ) == 0 ) + { + arg->inputFormatConfig.mcLayout = IVAS_ENC_MC_7_1; + } + else if ( strcmp( argv[i], "5_1_2" ) == 0 ) + { + arg->inputFormatConfig.mcLayout = IVAS_ENC_MC_5_1_2; + } + else if ( strcmp( argv[i], "5_1_4" ) == 0 ) + { + arg->inputFormatConfig.mcLayout = IVAS_ENC_MC_5_1_4; + } + else if ( strcmp( argv[i], "7_1_4" ) == 0 ) + { + arg->inputFormatConfig.mcLayout = IVAS_ENC_MC_7_1_4; + } + else + { + fprintf( stderr, "Error: Incorrect input configuration specified for Multi-channel\n\n" ); + usage_enc(); + return false; + } + i++; + } + else + { + fprintf( stderr, "Error: Multi-channel configuration not specified!\n\n" ); + usage_enc(); + return false; + } + } + 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(); + return false; + } + 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(); + return false; + } + } + } + else + { + fprintf( stderr, "Error: Number of ISM channels not specified!\n\n" ); + usage_enc(); + return false; + } + 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 be 1 or 2.\n\n" ); + usage_enc(); + return false; + } + } + + /* 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(); + return false; + } + } + + if ( i < argc - 4 ) + { + arg->masaMetadataFile = argv[i]; + i++; + } + else + { + fprintf( stderr, "Error: not enough MASA arguments\n\n" ); + usage_enc(); + return false; + } + } + else if ( strcmp( to_upper( argv[i] ), "-ISM_SBA" ) == 0 ) + { + arg->inputFormat = IVAS_ENC_INPUT_SBA_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(); + return false; + } + else + { + if ( tmp <= IVAS_MAX_NUM_OBJECTS ) /* number of ISM channels */ + { + arg->inputFormatConfig.sba_ism.numObjects = (int16_t) tmp; + } + else + { + fprintf( stderr, "Error: Too high number of ISM channels!\n\n" ); + usage_enc(); + return false; + } + } + } + else + { + fprintf( stderr, "Error: Number of ISM channels not specified!\n\n" ); + usage_enc(); + return false; + } + + if ( i < argc - 4 ) + { + if ( sscanf( argv[i], "%d", &tmp ) > 0 ) + { + i++; + } + + arg->inputFormatConfig.sba_ism.isPlanar = ( tmp < 0 ); + + tmp = abs( tmp ); + switch ( tmp ) + { + case 1: + arg->inputFormatConfig.sba_ism.order = IVAS_ENC_SBA_FOA; + break; + case 2: + arg->inputFormatConfig.sba_ism.order = IVAS_ENC_SBA_HOA2; + break; + case 3: + arg->inputFormatConfig.sba_ism.order = IVAS_ENC_SBA_HOA3; + break; + default: + fprintf( stderr, "Error: Wrong SBA order specified!\n\n" ); + usage_enc(); + return false; + } + } + + /* read input metadata files */ + for ( j = 0; j < arg->inputFormatConfig.sba_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.sba_ism.metadataFiles[j] = NULL; + } + else + { + arg->inputFormatConfig.sba_ism.metadataFiles[j] = argv[i]; + } + + i++; + } + else + { + fprintf( stderr, "Error: not enough arguments\n\n" ); + usage_enc(); + return false; + } + } + } + else if ( strcmp( argv_to_upper, "-STEREO_DMX_EVS" ) == 0 ) + { + arg->inputFormat = IVAS_ENC_INPUT_MONO; + arg->inputFormatConfig.stereoToMonoDownmix = true; + + i++; + } + else if ( strcmp( argv_to_upper, "-PCA" ) == 0 ) + { + arg->pca = 1; + i++; + } + +#ifdef IVAS_RTPDUMP + /*-----------------------------------------------------------------* + * RTPDump output + *-----------------------------------------------------------------*/ + + else if ( strcmp( argv_to_upper, "-RTPDUMP" ) == 0 ) + { + i++; + arg->rtpdumpOutput = true; + if ( i < argc - 4 ) + { + if ( !is_digits_only( argv[i] ) ) + { + arg->numFramesPerPacket = 1; /* Default to 1 frame per packet */ + } + else + { + arg->numFramesPerPacket = atoi( argv[i++] ); + if ( arg->numFramesPerPacket > IVAS_MAX_FRAMES_PER_RTP_PACKET ) + { + fprintf( stderr, "numFramesPerPacket(%d) exceeds max frames per packet (%d) \n", arg->numFramesPerPacket, IVAS_MAX_FRAMES_PER_RTP_PACKET ); + arg->numFramesPerPacket = 1; + } + } + } + fprintf( stdout, "Output format: RTPDump using %d frames/packet \n", arg->numFramesPerPacket ); + } + + /*-----------------------------------------------------------------* + * Scene orientation + *-----------------------------------------------------------------*/ + + else if ( strcmp( argv_to_upper, "-SCENE_ORIENTATION" ) == 0 ) + { + i++; + if ( argc - i <= 4 || argv[i][0] == '-' ) + { + fprintf( stderr, "Error: Scene orientation file name not specified!\n\n" ); + usage_enc(); + return false; + } + + arg->sceneOrientationTrajFileName = argv[i]; + i++; + } + + /*-----------------------------------------------------------------* + * Device orientation + *-----------------------------------------------------------------*/ + + else if ( strcmp( argv_to_upper, "-DEVICE_ORIENTATION" ) == 0 ) + { + i++; + if ( argc - i <= 4 || argv[i][0] == '-' ) + { + fprintf( stderr, "Error: Device orientation file name not specified!\n\n" ); + usage_enc(); + return false; + } + + arg->deviceOrientationTrajFileName = argv[i]; + i++; + } + +#endif + /*-----------------------------------------------------------------* + * Option not recognized + *-----------------------------------------------------------------*/ + else + { + fprintf( stderr, "Error: option not recognized, %s\n\n", argv[i] ); + usage_enc(); + return false; + } + } /* end of while */ + +#ifdef IVAS_RTPDUMP + if ( arg->sceneOrientationTrajFileName != NULL && arg->rtpdumpOutput == false ) + { + fprintf( stderr, "Error: Scene orientations are only enabled with rtpdump output!\n\n" ); + usage_enc(); + return false; + } + if ( arg->deviceOrientationTrajFileName != NULL && arg->rtpdumpOutput == false ) + { + fprintf( stderr, "Error: Device orientations are only enabled with rtpdump output!\n\n" ); + usage_enc(); + return false; + } + +#endif + /*-----------------------------------------------------------------* + * Mandatory input arguments + *-----------------------------------------------------------------*/ + + /*-----------------------------------------------------------------* + * Bitrate + *-----------------------------------------------------------------*/ + + if ( i < argc - 2 ) + { + /* check if profile file has been entered instead of a fixed bitrate */ + if ( !is_digits_only( argv[i] ) ) + { + arg->bitrateProfileFile = argv[i]; + } + else + { + arg->initBitrate = atoi( argv[i] ); + } + + i++; + } + else + { + fprintf( stderr, "Error: no bitrate specified\n\n" ); + usage_enc(); + return false; + } + + /*-----------------------------------------------------------------* + * Input sampling frequency + *-----------------------------------------------------------------*/ + + if ( i < argc - 2 ) + { + arg->inputFs = atoi( argv[i] ) * 1000; + i++; + } + else + { + fprintf( stderr, "Error: no input sampling frequency specified\n\n" ); + usage_enc(); + return false; + } + + /* for EVS mono, restore default behavior, i.e. SWB as default maxBandwidth if not set by the user otherwise */ + if ( arg->max_bwidth_user == false ) + { + arg->maxBandwidth = IVAS_ENC_GetDefaultBandwidth( ( arg->inputFormat == IVAS_ENC_INPUT_MONO ) ? true : false ); + } + + /* Prevent maxBandwidth from being higher than inputFs/2 */ + if ( arg->inputFs == 8000 && arg->maxBandwidth > IVAS_ENC_BANDWIDTH_NB ) + { + arg->maxBandwidth = IVAS_ENC_BANDWIDTH_NB; + } + else if ( arg->inputFs == 16000 && arg->maxBandwidth > IVAS_ENC_BANDWIDTH_WB ) + { + arg->maxBandwidth = IVAS_ENC_BANDWIDTH_WB; + } + else if ( arg->inputFs == 32000 && arg->maxBandwidth > IVAS_ENC_BANDWIDTH_SWB ) + { + arg->maxBandwidth = IVAS_ENC_BANDWIDTH_SWB; + } + + /*-----------------------------------------------------------------* + * Input file + *-----------------------------------------------------------------*/ + + if ( i < argc - 1 ) + { + arg->inputWavFilename = argv[i]; + i++; + } + else + { + fprintf( stderr, "Error: no input file specified\n\n" ); + usage_enc(); + return false; + } + + /*-----------------------------------------------------------------* + * Output bitstream file + *-----------------------------------------------------------------*/ + + if ( i < argc ) + { + arg->outputBitstreamFilename = argv[i]; + i++; + } + else + { + fprintf( stderr, "Error: no output bitstream file specified\n\n" ); + usage_enc(); + return false; + } + + return true; +} + + +/*---------------------------------------------------------------------* + * usage_enc() + * + * Print the usage of the "ivas_cod" program + *---------------------------------------------------------------------*/ + +static void usage_enc( void ) +{ + fprintf( stdout, "Usage: IVAS_cod.exe [Options] R Fs input_file bitstream_file\n\n" ); + + fprintf( stdout, "Mandatory parameters:\n" ); + fprintf( stdout, "---------------------\n" ); + + fprintf( stdout, "R : Bitrate in bps, \n" ); + fprintf( stdout, " for EVS native modes R = (5900*, 7200, 8000, 9600, 13200, 16400,\n" ); + fprintf( stdout, " 24400, 32000, 48000, 64000, 96000, 128000) \n" ); + fprintf( stdout, " *VBR mode (average bitrate),\n" ); + fprintf( stdout, " for AMR-WB IO modes R = (6600, 8850, 12650, 14250, 15850, 18250,\n" ); + fprintf( stdout, " 19850, 23050, 23850) \n" ); + fprintf( stdout, " for IVAS stereo R = (13200, 16400, 24400, 32000, 48000, 64000, 80000, \n" ); + fprintf( stdout, " 96000, 128000, 160000, 192000, 256000) \n" ); + fprintf( stdout, " for IVAS ISM R = 13200 for 1 ISM, 16400 for 1 ISM and 2 ISM, \n" ); + fprintf( stdout, " (24400, 32000, 48000, 64000, 80000, 96000, 128000) \n" ); + fprintf( stdout, " for 2 ISM, 3 ISM and 4 ISM also 160000, 192000, 256000) \n" ); + fprintf( stdout, " for 3 ISM and 4 ISM also 384000 \n" ); + fprintf( stdout, " for 4 ISM also 512000 \n" ); + fprintf( stdout, " for IVAS SBA, MASA, MC, ISM-SBA, and ISM-MASA R=(13200, 16400, 24400, 32000, 48000, 64000,\n" ); + fprintf( stdout, " 80000, 96000, 128000, 160000, 192000, 256000, 384000, 512000) \n" ); + 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" ); + fprintf( stdout, "Fs : Input sampling rate in kHz, Fs = (8, 16, 32 or 48) \n" ); + + fprintf( stdout, "input_file : Input audio filename \n" ); + fprintf( stdout, "bitstream_file : Output bitstream filename \n\n" ); + + fprintf( stdout, "Options:\n" ); + fprintf( stdout, "--------\n" ); + fprintf( stdout, "EVS mono is default, for IVAS choose one of the following: -stereo, -ism, -sba, -masa, -mc, -ism_sba, -ism_masa\n" ); + fprintf( stdout, "-stereo : Stereo format \n" ); + fprintf( stdout, "-ism (+)Ch Files : ISM format \n" ); + fprintf( stdout, " where Ch specifies the number of ISMs (1-4)\n" ); + fprintf( stdout, " where positive (+) indicates extended metadata (only 64 kbps and up) \n" ); + fprintf( stdout, " and Files specify input files containing metadata, one file per object\n" ); + fprintf( stdout, " (use NULL for no input metadata)\n" ); + fprintf( stdout, "-sba +/-Order : Scene Based Audio input format (Ambisonics ACN/SN3D),\n" ); + fprintf( stdout, " where Order specifies the Ambisionics order (1-3),\n" ); + fprintf( stdout, " where positive (+) means full 3D and negative (-) only 2D/planar components to be coded\n" ); + fprintf( stdout, "-masa Ch File : MASA format \n" ); + fprintf( stdout, " where Ch specifies the number of MASA input/transport channels (1 or 2): \n" ); + fprintf( stdout, " and File specifies input file containing parametric MASA metadata \n" ); + fprintf( stdout, "-ism_sba IsmCh +/-Order IsmFiles : SBA and ISM combined format\n" ); + fprintf( stdout, " where IsmCh specifies the number of ISMs (1-4)\n" ); + fprintf( stdout, " and Order specifies the SBA order (1 to 3) \n" ); + fprintf( stdout, " and IsmFiles specify input files containing ISM metadata, one file per object \n" ); + fprintf( stdout, "-ism_masa IsmCh MasaCh IsmFiles MasaFile : MASA and ISM combined format \n" ); + fprintf( stdout, " where IsmCh specifies the number of ISMs (1-4),\n" ); + fprintf( stdout, " MasaCh specifies the number of MASA input/transport channels (1-2), \n" ); + fprintf( stdout, " IsmFiles specify input files containing ISM metadata, one file per object, \n" ); + fprintf( stdout, " and MasaFile specifies input file containing parametric MASA metadata \n" ); + fprintf( stdout, "-mc InputConf : Multi-channel format\n" ); + fprintf( stdout, " where InputConf specifies the channel configuration: 5_1, 7_1, 5_1_2, 5_1_4, 7_1_4\n" ); + fprintf( stdout, " Loudspeaker positions are assumed to have azimuth and elevation as per \n" ); + fprintf( stdout, " ISO/IEC 23091-3:2018 Table 3. Channel order is as per ISO/IEC 23008-3:2015 Table 95.\n" ); + fprintf( stdout, " See readme.txt for details.\n" ); + fprintf( stdout, "-dtx D : Activate DTX mode, D = (0, 3-100) is the SID update rate\n" ); + fprintf( stdout, " where 0 = adaptive, 3-100 = fixed in number of frames,\n" ); + fprintf( stdout, " default is deactivated\n" ); + fprintf( stdout, "-dtx : Activate DTX mode with a SID update rate of 8 frames\n" ); + fprintf( stdout, " Note: DTX is supported in EVS, stereo, ISM, SBA up to 80kbps and MASA up to 128kbps \n" ); + fprintf( stdout, "-rf p o : Activate channel-aware mode for WB and SWB signal at 13.2kbps, \n" ); + fprintf( stdout, " where FEC indicator, p: LO or HI, and FEC offset, o: 2, 3, 5, or 7 in number of frames.\n" ); + fprintf( stdout, " Alternatively p and o can be replaced by a rf configuration file with each line \n" ); + fprintf( stdout, " contains the values of p and o separated by a space, \n" ); + fprintf( stdout, " default is deactivated \n" ); + fprintf( stdout, "-max_band B : Activate bandwidth limitation, B = (NB, WB, SWB or FB)\n" ); + fprintf( stdout, " alternatively, B can be a text file where each line contains \"nb_frames B\"\n" ); + fprintf( stdout, "-no_delay_cmp : Turn off delay compensation\n" ); + fprintf( stdout, "-stereo_dmx_evs : Activate stereo downmix function for EVS.\n" ); + fprintf( stdout, "-binaural : Optional indication that input is binaural audio (to be used with -stereo or -stereo_dmx_evs)\n" ); + fprintf( stdout, "-mime : Mime output bitstream file format\n" ); + fprintf( stdout, " The encoder produces TS26.445 Annex.2.6 Mime Storage Format, (not RFC4867 Mime Format).\n" ); + fprintf( stdout, " default output bitstream file format is G.192\n" ); + fprintf( stdout, "-pca : activate PCA in SBA format FOA at 256 kbps \n" ); + fprintf( stdout, "-level level : Complexity level, level = (1, 2, 3), will be defined after characterisation. \n" ); + fprintf( stdout, " Currently, all values default to level 3 (full functionality).\n" ); +#ifdef DEBUGGING + fprintf( stdout, "-force T : Force specific mode, T = (speech, music, ACELP, GSC, TCX, HQ),\n" ); + fprintf( stdout, " alternatively, T can be a text file where each line contains \"nb_frames T\"\n" ); +#ifdef DEBUG_SBA + fprintf( stdout, "-tag : Tag name for intermediate debug files\n" ); +#endif +#ifdef DEBUG_AGC_ENCODER_CMD_OPTION + fprintf( stdout, "-agc op : SBA Adaptive gain control, op = (0, 1). \n" ); + fprintf( stdout, " By default op is 1 (activated) for bitrates between 24400 and 32000,\n" ); + fprintf( stdout, " otherwise it is 0 (deactivated) for all other bitrates\n" ); +#endif +#ifdef DEBUG_MODE_INFO +#ifdef DEBUG_MODE_INFO_TWEAK + fprintf( stdout, "-info : specify subfolder name for debug output\n" ); +#endif +#endif +#endif + fprintf( stdout, "-q : Quiet mode, no frame counters\n" ); + fprintf( stdout, " default is deactivated\n" ); +#ifdef IVAS_RTPDUMP + fprintf( stdout, "-rtpdump : RTPDump output, hf_only=1 by default. The encoder will packetize the \n" ); + fprintf( stdout, " bitstream frames into TS26.253 Annex A IVAS RTP Payload Format packets and \n" ); + fprintf( stdout, " writes those to the output file. In EVS mono operating mode, TS26.445 Annex A.2.2 \n" ); + fprintf( stdout, " EVS RTP Payload Format is used. Optional N represents number of frames per RTP packet\n" ); + fprintf( stdout, "-scene_orientation : Scene orientation trajectory file. Only used with rtpdump output.\n" ); + fprintf( stdout, "-device_orientation : Device orientation trajectory file. Only used with rtpdump output.\n" ); +#endif + fprintf( stdout, "\n" ); + + return; +} + + +/*---------------------------------------------------------------------* + * readBandwidth() + * + * + *---------------------------------------------------------------------*/ + +static bool readBandwidth( + FILE *file, + IVAS_ENC_BANDWIDTH *bandwidth, + int32_t *bandwidthFrameCounter ) +{ + int16_t res; + char stmp[4]; + + if ( *bandwidthFrameCounter == 0 ) + { + /* read next bandwidth value and number of frames from the profile file */ + while ( ( res = (int16_t) fscanf( file, "%d %3s", bandwidthFrameCounter, stmp ) ) != 2 && feof( file ) ) + { + rewind( file ); + } + + ( *bandwidthFrameCounter )--; + + to_upper( stmp ); + + if ( strcmp( stmp, "NB" ) == 0 ) + { + *bandwidth = IVAS_ENC_BANDWIDTH_NB; + } + else if ( strcmp( stmp, "WB" ) == 0 ) + { + *bandwidth = IVAS_ENC_BANDWIDTH_WB; + } + else if ( strcmp( stmp, "SWB" ) == 0 ) + { + *bandwidth = IVAS_ENC_BANDWIDTH_SWB; + } + else if ( strcmp( stmp, "FB" ) == 0 ) + { + *bandwidth = IVAS_ENC_BANDWIDTH_FB; + } + else + { + fprintf( stderr, "Error: incorrect bandwidth specified (only NB, WB, SWB and FB are supported)\n\n" ); + usage_enc(); + return false; + } + } + else + { + /* current profile still active, only decrease the counter */ + ( *bandwidthFrameCounter )--; + } + + return true; +} + + +/*---------------------------------------------------------------------* + * readBitrate() + * + * + *---------------------------------------------------------------------*/ + +static bool readBitrate( + FILE *file, + int32_t *bitrate ) +{ + for ( int32_t i = 0; i < 2; ++i ) + { + if ( fread( bitrate, sizeof( int32_t ), 1, file ) == 1 ) + { + return true; + } + + rewind( file ); + } + + fprintf( stderr, "Error: cannot read the bitrate profile file\n\n" ); + usage_enc(); + return false; +} + + +#ifdef DEBUGGING +/*---------------------------------------------------------------------* + * parseForcedMode() + * + * + *---------------------------------------------------------------------*/ + +static IVAS_ENC_FORCED_MODE parseForcedMode( + char *forcedModeChar ) +{ + to_upper( forcedModeChar ); + + if ( ( strcmp( forcedModeChar, "SPEECH" ) == 0 ) || ( strcmp( forcedModeChar, "'SPEECH'" ) == 0 ) || + ( strcmp( forcedModeChar, "0" ) == 0 ) ) + { + return IVAS_ENC_FORCE_SPEECH; + } + if ( ( strcmp( forcedModeChar, "MUSIC" ) == 0 ) || ( strcmp( forcedModeChar, "'MUSIC'" ) == 0 ) || ( strcmp( forcedModeChar, "AUDIO" ) == 0 ) || ( strcmp( forcedModeChar, "'AUDIO'" ) == 0 ) || ( strcmp( forcedModeChar, "1" ) == 0 ) ) + { + return IVAS_ENC_FORCE_MUSIC; + } + if ( ( strcmp( forcedModeChar, "ACELP" ) == 0 ) || ( strcmp( forcedModeChar, "'ACELP'" ) == 0 ) ) + { + return IVAS_ENC_FORCE_ACELP; + } + if ( ( strcmp( forcedModeChar, "GSC" ) == 0 ) || ( strcmp( forcedModeChar, "'GSC'" ) == 0 ) ) + { + return IVAS_ENC_FORCE_GSC; + } + if ( ( strcmp( forcedModeChar, "TCX" ) == 0 ) || ( strcmp( forcedModeChar, "'TCX'" ) == 0 ) ) + { + return IVAS_ENC_FORCE_TCX; + } + if ( ( strcmp( forcedModeChar, "HQ" ) == 0 ) || ( strcmp( forcedModeChar, "'HQ'" ) == 0 ) ) + { + return IVAS_ENC_FORCE_HQ; + } + + return IVAS_ENC_FORCE_UNDEFINED; +} + + +/*---------------------------------------------------------------------* + * readForcedMode() + * + * + *---------------------------------------------------------------------*/ + +static ivas_error readForcedMode( + FILE *file, + IVAS_ENC_FORCED_MODE *forcedMode, + int32_t *forceFrameCounter ) +{ + int16_t res; + char stmp[8]; + + if ( *forceFrameCounter == 0 ) + { + /* read next force and number of frames from the profile file */ + while ( ( res = (int16_t) fscanf( file, "%d %7s", forceFrameCounter, stmp ) ) != 2 && feof( file ) ) + { + rewind( file ); + } + + *forcedMode = parseForcedMode( stmp ); + + if ( *forcedMode == IVAS_ENC_FORCE_UNDEFINED ) + { + fprintf( stderr, "Error: incorect mode specification or the force profile file could not be opened: %s\n\n", stmp ); + return IVAS_ERR_WRONG_PARAMS; + } + + if ( res != 2 && !feof( file ) ) + { + fprintf( stderr, "Error: incorrect format of the force profile file (please ensure that it does not contain any empty lines)\n\n" ); + return IVAS_ERR_WRONG_PARAMS; + } + } + + /* current profile still active, only decrease the counter */ + ( *forceFrameCounter )--; + + return IVAS_ERR_OK; +} +#endif + +#undef WMC_TOOL_SKIP diff --git a/apps/isar_post_rend.c b/apps/isar_post_rend.c index 7d8fd0939fe88432bceb8c600130ad9ba0794c52..96dc9b827fa0ec506ef6c8bf86bcef276b3896a2 100644 --- a/apps/isar_post_rend.c +++ b/apps/isar_post_rend.c @@ -749,6 +749,9 @@ static void trim( char *str ) static ivas_error parseSRParamsFile( const char *srParamsFilePath, +#ifdef RTP_SR_CODEC_FRAME_SIZE_IN_TOC_BYTE + const char *rtpFilePath, +#endif ISAR_SPLIT_REND_CODEC *codec, ISAR_SPLIT_REND_POSE_CORRECTION_MODE *poseCorrection, int16_t *codec_frame_size_ms, @@ -775,6 +778,24 @@ static ivas_error parseSRParamsFile( trim( key ); trim( value ); +#ifdef RTP_SR_CODEC_FRAME_SIZE_IN_TOC_BYTE + if ( 0 == strncmp( key, "DOF", 3 ) ) + { + int val = atoi( value ); + if ( val == 0 || val == 1 ) + { + *poseCorrection = ( val == 0 ) ? ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE : ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB; + } + } + else if ( 0 == strncmp( key, "LC3PLUS_HIGHRES", 15 ) ) + { + int val = atoi( value ); + if ( val == 0 || val == 1 ) + { + *lc3plusHighRes = (int16_t) val; + } + } +#else if ( 0 == strncmp( key, "CODEC", 5 ) ) { *codec = ( 0 == strncmp( value, "LCLD", 4 ) ) ? ISAR_SPLIT_REND_CODEC_LCLD : *codec; @@ -812,10 +833,52 @@ static ivas_error parseSRParamsFile( *lc3plusHighRes = (int16_t) val; } } +#endif } } fclose( fParamSR ); + +#ifdef RTP_SR_CODEC_FRAME_SIZE_IN_TOC_BYTE + { + /* Peek the RTP stream to ascertain the codec and codec_frame_size */ + ivas_error error = IVAS_ERR_OK; + IVAS_RTP srRtp = { 0 }; + if ( ( error = IVAS_RTP_READER_Init( &srRtp, rtpFilePath, NULL, false, NULL ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "error in IVAS_RTP_READER_Init() for sr RTP peek: %d\n", error ); + return error; + } + + /* read a frame */ + while ( 1 ) + { + bool qBit = false; + IVAS_RTP_SR_INFO srInfo = { 0 }; + uint8_t au[( IVAS_MAX_BITS_PER_FRAME + 7 ) >> 3]; + int16_t auSize = 0; + uint16_t rtpSequenceNumber = 0; + uint32_t rtpTimeStamp = 0, nextPacketRcvTime_ms = 0; + + error = IVAS_RTP_ReadNextFrame( &srRtp, au, &auSize, &rtpTimeStamp, &rtpSequenceNumber, &nextPacketRcvTime_ms, &srInfo, &qBit ); + if ( error != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError in IVAS_RTP_ReadNextFrame, error code: %d\n", error ); + return error; + } + + if ( srInfo.valid ) + { + *codec = ( srInfo.codec == IVAS_SR_TRANSPORT_LCLD ) ? ISAR_SPLIT_REND_CODEC_LCLD : ISAR_SPLIT_REND_CODEC_LC3PLUS; + *codec_frame_size_ms = (int16_t) srInfo.codecFrameSizeMs; + *isar_frame_size_ms = *codec_frame_size_ms; /* for rtp force codec framesize as isar renderer frame size */ + break; + } + } + IVAS_RTP_Term( &srRtp ); + } +#endif + return IVAS_ERR_OK; } #endif @@ -949,6 +1012,9 @@ int main( if ( ( args.inConfig.numBinBuses > 0 ) && ( args.inConfig.binBuses[0].srRtp ) ) { error = parseSRParamsFile( args.srParamsFilePath, +#ifdef RTP_SR_CODEC_FRAME_SIZE_IN_TOC_BYTE + args.inputFilePath, +#endif &bitsBuffer.config.codec, &bitsBuffer.config.poseCorrection, &bitsBuffer.config.codec_frame_size_ms, @@ -960,12 +1026,20 @@ int main( goto cleanup; } +#ifndef RTP_SR_CODEC_FRAME_SIZE_IN_TOC_BYTE if ( ( error = IVAS_RTP_READER_Init( &srRTP, (uint32_t) bitsBuffer.config.codec_frame_size_ms, args.inputFilePath, NULL, false, NULL ) ) != IVAS_ERR_OK ) +#else + if ( ( error = IVAS_RTP_READER_Init( &srRTP, args.inputFilePath, NULL, false, NULL ) ) != IVAS_ERR_OK ) +#endif { fprintf( stderr, "error in IVAS_RTP_READER_Init(): %d\n", error ); goto cleanup; } audioReader = NULL; +#ifdef RTP_SR_CODEC_FRAME_SIZE_IN_TOC_BYTE + /* Force owerwrite of command line provided rendersize to align with codec frame size */ + args.render_framesize = bitsBuffer.config.isar_frame_size_ms / 5; +#endif } /*if split renderer is running in post renderer mode*/ else if ( ( args.inConfig.numBinBuses > 0 ) && ( args.inConfig.binBuses[0].audioConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) ) @@ -1195,6 +1269,9 @@ int main( if ( error == IVAS_ERR_END_OF_FILE ) { numSamplesRead = 0; +#ifdef RTP_SR_CODEC_FRAME_SIZE_IN_TOC_BYTE + break; +#endif } else { diff --git a/apps/renderer.c b/apps/renderer.c index e434c0ca2a2193c674c2919cf2737efab37db3ed..753a116c157fadabbb01e81f01d0b9ea1c8f094c 100644 --- a/apps/renderer.c +++ b/apps/renderer.c @@ -200,6 +200,9 @@ typedef struct IVAS_RENDER_FRAMESIZE render_framesize; uint16_t directivityPatternId[RENDERER_MAX_ISM_INPUTS]; AcousticEnvironmentSequence aeSequence; +#ifdef FIX_1318_ROOM_SIZE_CMD_LINE + IVAS_ROOM_SIZE_T reverbRoomSize; +#endif } CmdlnArgs; typedef enum @@ -230,7 +233,12 @@ typedef enum CmdLnOptionId_framing, CmdLnOptionId_syncMdDelay, CmdLnOptionId_directivityPatternId, +#ifdef FIX_1318_ROOM_SIZE_CMD_LINE + CmdLnOptionId_acousticEnvironmentId, + CmdLnOptionId_roomSize, +#else CmdLnOptionId_acousticEnvironmentId +#endif } CmdLnOptionId; static const CmdLnParser_Option cliOptions[] = { @@ -396,6 +404,14 @@ static const CmdLnParser_Option cliOptions[] = { .matchShort = "aeid", .description = "Acoustic environment ID (number > 0) alternatively, it can be\na text file where each line contains \"ID duration\" for\nBINAURAL_ROOM_REVERB output.", }, +#ifdef FIX_1318_ROOM_SIZE_CMD_LINE + { + .id = CmdLnOptionId_roomSize, + .match = "room_size", + .matchShort = "rsz", + .description = "Selects default reverb based on a room size (S - small | M - medium | L - large)", + } +#endif }; @@ -1160,6 +1176,18 @@ int main( fprintf( stderr, "\nError in IVAS_REND_SetOrientationTrackingMode(): %s\n", ivas_error_to_string( error ) ); goto cleanup; } +#ifdef FIX_1318_ROOM_SIZE_CMD_LINE + + /* Set reverb room size if specified */ + if ( args.reverbRoomSize != IVAS_ROOM_SIZE_AUTO ) + { + if ( ( IVAS_REND_SetReverbRoomSize( hIvasRend, args.reverbRoomSize ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError setting reverb room size\n" ); + goto cleanup; + } + } +#endif /* Set up output custom layout configuration */ if ( args.outConfig.audioConfig == IVAS_AUDIO_CONFIG_LS_CUSTOM ) @@ -1421,7 +1449,16 @@ int main( audioWriter = NULL; } +#ifdef FIX_1437_LC3PLUS_EXTREND_HIRES + if ( ( error = IVAS_REND_GetSplitRendBitstreamHeader( hIvasRend, + &bitsBuffer.config.codec, + &bitsBuffer.config.poseCorrection, + &bitsBuffer.config.codec_frame_size_ms, + &bitsBuffer.config.isar_frame_size_ms, + &bitsBuffer.config.lc3plus_highres ) ) != IVAS_ERR_OK ) +#else if ( ( error = IVAS_REND_GetSplitRendBitstreamHeader( hIvasRend, &bitsBuffer.config.codec, &bitsBuffer.config.poseCorrection, &bitsBuffer.config.codec_frame_size_ms, &bitsBuffer.config.isar_frame_size_ms ) ) != IVAS_ERR_OK ) +#endif { fprintf( stderr, "\nError in IVAS_REND_GetSplitRendBitstreamHeader()!\n" ); goto cleanup; @@ -2551,6 +2588,39 @@ static bool parseAcousticEnvironmentIds( return true; } +#ifdef FIX_1318_ROOM_SIZE_CMD_LINE + + +static bool parseReverbRoomSize( + char *value, + IVAS_ROOM_SIZE_T *reverbRoomSize ) +{ + if ( strlen( value ) != 1 ) + { + fprintf( stderr, "Error: Unsupported room size selector %s!\n\n", value ); + return false; + } + + to_upper( value ); + switch ( value[0] ) + { + case 'S': + *reverbRoomSize = IVAS_ROOM_SIZE_SMALL; + break; + case 'M': + *reverbRoomSize = IVAS_ROOM_SIZE_MEDIUM; + break; + case 'L': + *reverbRoomSize = IVAS_ROOM_SIZE_LARGE; + break; + default: + fprintf( stderr, "Error: Unsupported room size selector %s!\n\n", value ); + return false; + } + + return true; +} +#endif static bool checkRequiredArgs( @@ -2672,6 +2742,10 @@ static CmdlnArgs defaultArgs( args.aeSequence.pValidity = NULL; args.aeSequence.selected = 0; args.aeSequence.frameCounter = 0; +#ifdef FIX_1318_ROOM_SIZE_CMD_LINE + + args.reverbRoomSize = IVAS_ROOM_SIZE_AUTO; +#endif return args; } @@ -2857,6 +2931,16 @@ static void parseOption( args->syncMdDelay = strtof( optionValues[0], NULL ); #endif break; +#ifdef FIX_1318_ROOM_SIZE_CMD_LINE + case CmdLnOptionId_roomSize: + assert( numOptionValues == 1 ); + if ( !parseReverbRoomSize( optionValues[0], &args->reverbRoomSize ) ) + { + fprintf( stderr, "Error: Unsupported room size selector %s!\n\n", optionValues[0] ); + exit( -1 ); + } + break; +#endif default: assert( 0 && "This should be unreachable - all command line options should be explicitly handled." ); break; diff --git a/ivas_be_conf_test_gen.sh b/ivas_be_conf_test_gen.sh deleted file mode 100644 index db23621c4a7060e471fde05dc10531b34ea443d1..0000000000000000000000000000000000000000 --- a/ivas_be_conf_test_gen.sh +++ /dev/null @@ -1,46 +0,0 @@ -#! /bin/sh - -set -e - -make -f Makefile clean -make -f Makefile -j"$(nproc)" CLANG=0 -cp IVAS_cod IVAS_cod_ref -cp IVAS_dec IVAS_dec_ref -cp IVAS_rend IVAS_rend_ref -cp ISAR_post_rend ISAR_post_rend_ref -python3 scripts/prepare_combined_format_inputs.py -python3 -m pytest -q tests/codec_be_on_mr_nonselection tests/renderer_short/test_renderer.py tests/split_rendering/test_split_rendering.py -v -n auto --update_ref 1 --create_ref --keep_files --html=report_cmd.html --self-contained-html -python3 scripts/parse_commands.py report_cmd.html Readme_IVAS.txt -rm -rf testvec -mkdir testvec -mkdir testvec/binauralRenderer_interface -mkdir testvec/testv -mkdir testvec/testv/renderer_short -mkdir testvec/testv/split_rendering -mkdir testvec/bin -cp -r scripts/testv/* testvec/testv -cp -r scripts/ls_layouts testvec -cp -r scripts/object_edit testvec -cp -r scripts/switchPaths testvec -cp -r scripts/trajectories testvec -cp -r scripts/binauralRenderer_interface/binaural_renderers_hrtf_data testvec/binauralRenderer_interface -cp -r tests/ref testvec/testv/ref -cp -r tests/renderer_short/ref testvec/testv/renderer_short/ref -cp -r tests/split_rendering/ref testvec/testv/split_rendering/ref -cp -r tests/split_rendering/renderer_configs testvec/testv/split_rendering/renderer_configs -cp -r tests/split_rendering/error_patterns testvec/testv/split_rendering/error_patterns - -python3 scripts/cleanup_26252.py - -cp -r tests/conformance-test testvec/ -cp Readme_IVAS_dec.txt testvec -cp Readme_IVAS_enc.txt testvec -cp Readme_IVAS_rend.txt testvec -cp Readme_IVAS_JBM_dec.txt testvec -cp Readme_IVAS_ISAR_dec.txt testvec -cp Readme_IVAS_ISAR_post_rend.txt testvec - -cp IVAS_cod testvec/bin -cp IVAS_dec testvec/bin -cp IVAS_rend testvec/bin -cp ISAR_post_rend testvec/bin diff --git a/lib_com/common_api_types.h b/lib_com/common_api_types.h index 80c90d6b3152a5ace3ef0f0f205ac0c61784a356..f4a75208b67140276c09a15db939e95448e89127 100644 --- a/lib_com/common_api_types.h +++ b/lib_com/common_api_types.h @@ -59,6 +59,9 @@ #define IVAS_ROOM_ABS_COEFF 6 #define IVAS_REVERB_PREDELAY_MAX 20 /* Max input delay for reverb module */ #define IVAS_ER_LIST_HEIGHT 1.6f +#ifdef IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT +#define IVAS_DEFAULT_AEID 65535 +#endif /* JBM constants for adaptive-playout */ #define IVAS_TIME_SCALE_MIN 50 /* min. time-scaling [%] */ @@ -173,6 +176,16 @@ typedef enum } IVAS_RENDER_FRAMESIZE; +#ifdef FIX_1318_ROOM_SIZE_CMD_LINE +typedef enum +{ + IVAS_ROOM_SIZE_AUTO = -1, + IVAS_ROOM_SIZE_SMALL, + IVAS_ROOM_SIZE_MEDIUM, + IVAS_ROOM_SIZE_LARGE +} IVAS_ROOM_SIZE_T; +#endif + typedef struct ivas_masa_metadata_frame_struct *IVAS_MASA_METADATA_HANDLE; typedef struct ivas_masa_decoder_ext_out_meta_struct *IVAS_MASA_DECODER_EXT_OUT_META_HANDLE; @@ -312,6 +325,9 @@ typedef enum #endif typedef struct _IVAS_ROOM_ACOUSTICS_CONFIG { +#ifdef IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT + uint16_t aeID; /* Acoustic environment ID*/ +#endif int16_t nBands; /* Number of frequency bands for which reverb properties are provided, integer, range [2..256] */ float pFc_input[IVAS_CLDFB_NO_CHANNELS_MAX]; /* Center frequencies for which following values are provided: */ float pAcoustic_rt60[IVAS_CLDFB_NO_CHANNELS_MAX]; /* - The room's T60 per center frequency */ diff --git a/lib_com/ivas_cnst.h b/lib_com/ivas_cnst.h index 3e8521f47d8f5fc485771b6c1ce76bfaffcf783d..2d3c7e969a674a27491e52e640886b15b23e4e1b 100644 --- a/lib_com/ivas_cnst.h +++ b/lib_com/ivas_cnst.h @@ -177,6 +177,12 @@ typedef enum #define MAX_SPAR_INTERNAL_CHANNELS IVAS_SPAR_MAX_CH #define MAX_CLDFB_DIGEST_CHANNELS 3 /* == maximum of ParamISM TCs and ParamMC TCs */ +#ifdef FIX_GAIN_EDIT_LIMITS +#define EDIT_GAIN_MIN 0.0630957f /* Minimum allowed gain edit with parametric modes: -24 dB */ +#define EDIT_GAIN_MAX 3.9810719f /* Maximum allowed gain edit: +12 dB */ +#endif + + typedef enum { TC_BUFFER_MODE_RENDERER, @@ -1251,7 +1257,11 @@ typedef enum *----------------------------------------------------------------------------------*/ #define MC_LS_SETUP_BITS 3 /* number of bits for writing the MC LS configuration */ +#ifdef FIX_1419_MONO_STEREO_UMX +#define LS_SETUP_CONVERSION_NUM_MAPPINGS 41 /* number of mappings for LS setup conversion */ +#else #define LS_SETUP_CONVERSION_NUM_MAPPINGS 35 /* number of mappings for LS setup conversion */ +#endif typedef enum { @@ -1483,6 +1493,10 @@ typedef enum #define VBAP_NUM_SEARCH_SECTORS 4 +#ifdef NONBE_FIX_1426_STEREO_PANNING_BETWEEN_OPT_LEVEL +#define LS_ANGLE_RAD_30_DEG 0.52359879f /* 30.0f * PI_OVER_180 */ +#define INV_TAN_LS_ANGLE_RAD_30_DEG 1.7320507f /* 1.0f/tanf(30.0f * PI_OVER_180) */ +#endif /*----------------------------------------------------------------------------------* * Binaural Rendering Constants @@ -1587,11 +1601,26 @@ typedef enum #define RV_FILTER_MAX_HISTORY ( 512 - 160 ) /* for longest history */ #define RV_LENGTH_NR_FC ( RV_FILTER_MAX_FFT_SIZE / 2 ) + 1 #define RV_LENGTH_NR_FC_16KHZ ( RV_FILTER_MAX_FFT_SIZE / 4 ) + 1 +#ifdef FIX_1318_ROOM_SIZE_CMD_LINE +#define IVAS_REVERB_DEFAULT_L_N_BANDS 31 +#define IVAS_REVERB_DEFAULT_M_N_BANDS 31 +#define IVAS_REVERB_DEFAULT_S_N_BANDS 60 +#else #define IVAS_REVERB_DEFAULT_N_BANDS 31 +#endif #define LR_IAC_LENGTH_NR_FC ( RV_LENGTH_NR_FC ) #define LR_IAC_LENGTH_NR_FC_16KHZ ( RV_LENGTH_NR_FC_16KHZ ) +#ifdef FIX_1318_ROOM_SIZE_CMD_LINE +typedef enum +{ + DEFAULT_REVERB_UNSET = -1, + DEFAULT_REVERB_SMALL, + DEFAULT_REVERB_MEDIUM, + DEFAULT_REVERB_LARGE, +} IVAS_DefaultReverbSize; +#endif /*----------------------------------------------------------------------------------* * FB mixer constants diff --git a/lib_com/ivas_prot.h b/lib_com/ivas_prot.h index 5a3d62745498bb25433a1fff343581d377324e87..3699782aa7789b43210ffec63e682676dbde2e18 100644 --- a/lib_com/ivas_prot.h +++ b/lib_com/ivas_prot.h @@ -253,7 +253,7 @@ ivas_error ivas_compute_core_buffers( /*! r: number of clipped samples */ uint32_t ivas_syn_output( - float *synth[], /* i/o: float synthesis signal */ + float *synth[], /* i/o: float synthesis signal */ const int16_t output_frame, /* i : output frame length (one channel) */ const int16_t n_channels, /* i : number of output channels */ int16_t *synth_out /* o : integer 16 bits synthesis signal */ @@ -3233,7 +3233,7 @@ void ivas_qmetadata_enc_sid_encode( IVAS_QMETADATA *q_metadata, /* i/o: metadata handle */ const int16_t masa_sid_descriptor, /* i : description of MASA SID coding structure*/ const int16_t nchan_transport, /* i : number of transport channels */ - const int16_t ivas_format /* i : ivas format */ + const int16_t ivas_format /* i : ivas format */ ); /*! r: number of bits read */ @@ -3641,7 +3641,7 @@ ivas_error ivas_dirac_enc( const int16_t dtx_vad, /* i : DTX vad flag */ const IVAS_FORMAT ivas_format, /* i : ivas format */ const int16_t nchan_transport, /* i : number of transport channels */ - const int16_t hodirac_flag /* i : hodirac flag */ + const int16_t hodirac_flag /* i : hodirac flag */ ); ivas_error ivas_dirac_config( @@ -4141,7 +4141,7 @@ ivas_error ivas_sba_linear_renderer( float *output_f[], /* i/o: synthesized core-coder transport channels/DirAC output */ const int16_t output_frame, /* i : output frame length per channel */ const int16_t nchan_in, /* i : number of input ambisonics channels */ - const int16_t nchan_ism, /* i : number of objects */ + const int16_t nchan_ism, /* i : number of objects */ const AUDIO_CONFIG output_config, /* i : output audio configuration */ const IVAS_OUTPUT_SETUP output_setup /* i : output format setup */ ); @@ -4258,7 +4258,7 @@ int16_t ivas_get_sba_num_TCs( void ivas_spar_set_bitrate_config( ivas_spar_md_com_cfg *pSpar_md_cfg, /* i/o: SPAR MD config. handle */ const int16_t table_idx, /* i : config. table index */ - const int16_t num_bands, /* i : number of bands */ + const int16_t num_bands, /* i : number of bands */ const int16_t dirac2spar_md_flag, const int16_t enc_flag, const int16_t pca_flag, @@ -4550,7 +4550,7 @@ ivas_error ivas_spar_covar_enc_open( const int32_t input_Fs, /* i : input sampling rate */ const int16_t nchan_inp, /* i : number of input channels */ const COV_SMOOTHING_TYPE smooth_mode, /* i : Smooth covariance for SPAR or MC */ - const int32_t ivas_total_brate /* i : IVAS total bitrate */ + const int32_t ivas_total_brate /* i : IVAS total bitrate */ ); void ivas_spar_covar_enc_close( diff --git a/lib_com/options.h b/lib_com/options.h old mode 100755 new mode 100644 index 6dcb2f491a6dd529b837fe33bfa05ce8f6a6704e..7aa9f1c91547b45b18620de0c0715d221efc4f31 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -161,7 +161,14 @@ #define RTP_S4_251135_CR26253_0016_REV1 /* RTP Pack/Unpack API corresponding to CR 26253 */ #define IVAS_RTPDUMP /* RTPDUMP writing and reading for IVAS payloads */ +#define IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT /* RTPDUMP acoustic environment */ #define FIXED_RTP_SEQUENCE_NUM /* Remove random sequence number initialization */ +#define PI_LATENCY /* Pi latency PI frame */ +#define ISM_PI_DATA /* Add reading and packing/unpacking of ISM PI data */ +#define REVERSE_ISM_PI_DATA /* Add reading and packing/unpacking of reverse ISM PI data */ +#define DECODER_FORMAT_SWITCHING /* Re-initialize the decoder when the format/subformat of the incoming stream is changed */ +#define RTP_SR_CODEC_FRAME_SIZE_IN_TOC_BYTE /* CR for split rendering codec framesize signalling in Toc Byte*/ +#define FIX_SPLIT_RENDERING_ON_DECODER_RESTART /* Re-configure split rendering on decoder restart */ /* ################### Start BE switches ################################# */ /* only BE switches wrt selection floating point code */ @@ -171,7 +178,11 @@ #define TMP_1342_WORKAROUND_DEC_FLUSH_BROKEN_IN_SR /* FhG: Temporary workaround for incorrect implementation of decoder flush with split rendering */ #define FIX_1413_IGF_INIT_PRINTOUT /* FhG: use correct variable for IGF initiliazation */ #define RENDERER_MD_SYNC_DELAY_TO_INTEGER /* FhG: change data type of metadata sync delay in ext renderer to int16_t for better BASOP portability (and nicer code) */ +#define FIX_1427_OBJ_EDITING_EXT_METADATA /* Eri: Add support for extended metadata in object editing */ +#define FIX_1419_MONO_STEREO_UMX /* FhG: fix for issue 1419 : support upmix to all output formats for mono and stereo */ +#define FIX_1437_LC3PLUS_EXTREND_HIRES /* FhG: fix external renderer split bitstream header writing causing a crash for LC3plus High-res mode */ +#define FIX_1318_ROOM_SIZE_CMD_LINE /* Philips/Nokia: Default room sizes support */ /* #################### End BE switches ################################## */ @@ -192,6 +203,16 @@ #define NONBE_1324_TC_BUFFER_MEMOERY_KEEP /* VA: issue 1324: do not reset TSM memory in JBM bitrate switching */ #define FIX_1330_JBM_MEMORY_FIX /* VA: basop issue: 2179 fix non-BE difference in FIX_1330_JBM_MEMORY */ #define NONBE_1380_OMASA_BUILD_DIFF /* Nokia: Fix for issue #1380: Large differences in OMASA output between Debug and Release builds */ +#define NONBE_FIX_1426_STEREO_PANNING_BETWEEN_OPT_LEVEL /* Nokia: Adjustments in remaining stereo panning functions to make them BE between Debug and Release */ +#define FIX_GAIN_EDIT_LIMITS /* Harmonize gain edit limits for all opertation points. For all modes, limit to max +12dB. For parametric modes, limit to min -24dB. */ +#define BE_FIX_1391_COVERAGE_SPAR_DYN__CHANNEL /* Dolby: Fix coverage of SBA SPAR Dynamic active W not getting hit by the tests */ +#define NONBE_FIX_1442_MASA_EXT_REND_ORIENT_IDX /* Nokia: Fix issue 1442 of wrong index to combinedOrientationData */ + +#define FIX_1430_EVS_STEREO_DMX_CHANNEL_DISAPPEARING /* Orange: Fix for basop issue 2184 - to prevent one channel from becoming inaudible in the mono downmix output */ +#define FIX_1440_AMR_WB_RESET /* VA: issue 1440: Fix missing AMR-WB IO memory reset (applicable to float only) */ +#define FIX_BASOP_ISSUE_1585_CUT_BS_CRASH /* FhG: Fix for BASOP issue 1585 crash of a cut bitstream, also valid for float code*/ + +#define NONBE_FIX_BASOP_2233_RTPDUMP_DIFFERING_BITSTREAMS /* Nokia: fix basop issue 2233: Fix differing rtpdump streams */ /* ##################### End NON-BE switches ########################### */ diff --git a/lib_debug/debug.c b/lib_debug/debug.c index 012183c5ac9e392b1114723e5a698c8df7a87118..6ea62a4a46cf3d8cdfc5b71081b1df27b597e1a7 100644 --- a/lib_debug/debug.c +++ b/lib_debug/debug.c @@ -774,8 +774,13 @@ char *fname( { char idd[6]; +#ifdef BE_FIX_1391_COVERAGE_SPAR_DYN__CHANNEL + assert( id >= 0 && id < 100 ); + snprintf( idd, sizeof( idd ), ".id%d", id ); +#else assert( id < 100 ); sprintf( idd, ".id%d", id ); +#endif strcpy( tmp_fname, dir ); strcat( tmp_fname, file ); diff --git a/lib_dec/amr_wb_dec.c b/lib_dec/amr_wb_dec.c index 1b4712da1100fe3c9bc9de5538c19e16dde1ffc1..bbb0c7b10d6aa529a0c0b8e505a699d94e152a6d 100644 --- a/lib_dec/amr_wb_dec.c +++ b/lib_dec/amr_wb_dec.c @@ -295,6 +295,17 @@ ivas_error amr_wb_dec( st->bfi_pitch_frame = L_FRAME; } +#ifdef FIX_1440_AMR_WB_RESET + if ( st->last_core != AMR_WB_CORE ) + { + /* reset the unvoiced/audio signal improvement memories */ + isp2a( st->lsp_old, st->hAmrwb_IO->old_Aq, M ); + mvr2r( st->hAmrwb_IO->old_Aq, st->hAmrwb_IO->old_Aq + ( M + 1 ), M + 1 ); + mvr2r( st->hAmrwb_IO->old_Aq, st->hAmrwb_IO->old_Aq + 2 * ( M + 1 ), M + 1 ); + mvr2r( st->hAmrwb_IO->old_Aq, st->hAmrwb_IO->old_Aq + 3 * ( M + 1 ), M + 1 ); + } + +#endif if ( st->last_bwidth == NB && st->ini_frame != 0 ) { st->rate_switching_reset = 1; diff --git a/lib_dec/core_switching_dec.c b/lib_dec/core_switching_dec.c index 6445970f2a9309bce07356f9ef270e1d315b7668..f9ba20e70774938fafbd72e840c7f3a11706b7e1 100644 --- a/lib_dec/core_switching_dec.c +++ b/lib_dec/core_switching_dec.c @@ -663,7 +663,7 @@ ivas_error core_switching_post_dec( } else if ( ( ( st->last_core == ACELP_CORE || st->last_core_bfi == ACELP_CORE ) && !( st->prev_bfi == 1 && st->last_con_tcx == 1 ) ) || st->last_core == AMR_WB_CORE ) /*ACELP->TCX/HQ*/ { - /* if this is first active MDCT-Stereo frame after a CNG frame and output format is mono DMX, this should only be done for the zero-th channel, the other one will simply be copied over after this function */ + /* if output format is mono DMX, this should only be done for the zero-th channel, the other one will simply be copied over after this function */ if ( ( ( st->last_core_brate != SID_2k40 && st->last_core_brate != FRAME_NO_DATA ) || ( st->element_mode != IVAS_CPE_DFT && st->element_mode != IVAS_CPE_TD ) || nchan_out == 1 ) && !( st->element_mode == IVAS_CPE_MDCT && st->idchan == 1 && ( nchan_out == 1 || last_element_mode == IVAS_CPE_DFT ) ) ) { core_switch_lb_upsamp( st, output ); diff --git a/lib_dec/ivas_init_dec.c b/lib_dec/ivas_init_dec.c index 7e09074af0431592f1b423e7985adcbda5c6ee82..aa544ce6b81ef070d83d0668ad4145e3b002f2e5 100644 --- a/lib_dec/ivas_init_dec.c +++ b/lib_dec/ivas_init_dec.c @@ -106,6 +106,9 @@ ivas_error ivas_dec_get_format( int16_t nchan_ism, element_mode_flag; int16_t sba_order, sba_planar, sba_analysis_order; int32_t ivas_total_brate; +#ifdef DECODER_FORMAT_SWITCHING + int16_t Opt_tsm; +#endif uint16_t *bit_stream_orig; AUDIO_CONFIG signaled_config; ivas_error error; @@ -114,6 +117,9 @@ ivas_error ivas_dec_get_format( element_mode_flag = 0; ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; +#ifdef DECODER_FORMAT_SWITCHING + Opt_tsm = st_ivas->hDecoderConfig->Opt_tsm; +#endif bit_stream_orig = st_ivas->bit_stream; /*-------------------------------------------------------------------* @@ -129,10 +135,23 @@ ivas_error ivas_dec_get_format( !( st_ivas->ivas_format == MASA_FORMAT && st_ivas->last_ivas_format == MASA_ISM_FORMAT ) && !( st_ivas->ivas_format == MASA_ISM_FORMAT && st_ivas->last_ivas_format == MASA_FORMAT ) ) { +#ifdef DECODER_FORMAT_SWITCHING + if ( Opt_tsm ) + { + st_ivas->restartNeeded = 1; + + return IVAS_ERR_OK; + } + else + { +#endif #ifdef DEBUGGING - fprintf( stderr, "\nError: Changing the number of ISMs is not supported!\n" ); + fprintf( stderr, "\nError: Changing the number of ISMs is not supported!\n" ); +#endif + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Wrong number of objects signalled!" ); +#ifdef DECODER_FORMAT_SWITCHING + } #endif - return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Wrong number of objects signalled!" ); } /*-------------------------------------------------------------------* @@ -166,10 +185,23 @@ ivas_error ivas_dec_get_format( if ( st_ivas->ini_frame > 0 && nchan_ism != st_ivas->nchan_ism ) { +#ifdef DECODER_FORMAT_SWITCHING + if ( Opt_tsm ) + { + st_ivas->restartNeeded = 1; + + return IVAS_ERR_OK; + } + else + { +#endif #ifdef DEBUGGING - fprintf( stderr, "\nError: Changing the number of ISMs is not supported!\n" ); + fprintf( stderr, "\nError: Changing the number of ISMs is not supported!\n" ); +#endif + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Wrong number of objects signalled!" ); +#ifdef DECODER_FORMAT_SWITCHING + } #endif - return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Wrong number of objects signalled!" ); } st_ivas->nchan_ism = nchan_ism; @@ -189,10 +221,22 @@ ivas_error ivas_dec_get_format( if ( st_ivas->ini_frame > 0 && sba_planar != st_ivas->sba_planar ) { +#ifdef DECODER_FORMAT_SWITCHING + if ( Opt_tsm ) + { + st_ivas->restartNeeded = 1; + return IVAS_ERR_OK; + } + else + { +#endif #ifdef DEBUGGING - fprintf( stderr, "\nError: Changing the SBA planar/3D layout is not supported!\n" ); + fprintf( stderr, "\nError: Changing the SBA planar/3D layout is not supported!\n" ); +#endif + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Wrong SBA planar flag signalled!" ); +#ifdef DECODER_FORMAT_SWITCHING + } #endif - return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Wrong SBA planar flag signalled!" ); } /* read Ambisonic (SBA) order */ @@ -201,10 +245,23 @@ ivas_error ivas_dec_get_format( if ( st_ivas->ini_frame > 0 && sba_order != st_ivas->sba_order ) { +#ifdef DECODER_FORMAT_SWITCHING + if ( Opt_tsm ) + { + st_ivas->restartNeeded = 1; + + return IVAS_ERR_OK; + } + else + { +#endif #ifdef DEBUGGING - fprintf( stderr, "\nError: Changing the SBA order is not supported!\n" ); + fprintf( stderr, "\nError: Changing the SBA order is not supported!\n" ); +#endif + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Wrong SBA order signalled!" ); +#ifdef DECODER_FORMAT_SWITCHING + } #endif - return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Wrong SBA order signalled!" ); } sba_analysis_order = ivas_sba_get_analysis_order( ivas_total_brate, sba_order ); @@ -212,14 +269,30 @@ ivas_error ivas_dec_get_format( } else if ( st_ivas->ivas_format == MASA_FORMAT ) { +#ifdef DECODER_FORMAT_SWITCHING + uint8_t masaRestartCandidate = 0; +#endif + /* read number of MASA transport channels */ if ( st_ivas->bit_stream[( ivas_total_brate / FRAMES_PER_SEC ) - 1] ) { +#ifdef DECODER_FORMAT_SWITCHING + if ( st_ivas->nchan_transport == 1 && Opt_tsm ) + { + masaRestartCandidate = 1; + } +#endif st_ivas->nchan_transport = 2; element_mode_flag = 1; } else { +#ifdef DECODER_FORMAT_SWITCHING + if ( st_ivas->nchan_transport == 2 && Opt_tsm ) + { + masaRestartCandidate = 1; + } +#endif st_ivas->nchan_transport = 1; } @@ -247,13 +320,34 @@ ivas_error ivas_dec_get_format( st_ivas->nchan_transport = 2; element_mode_flag = 1; } +#ifdef DECODER_FORMAT_SWITCHING + else if ( masaRestartCandidate > 0 ) + { + st_ivas->restartNeeded = 1; + + return IVAS_ERR_OK; + } +#endif if ( st_ivas->ini_frame > 0 && nchan_ism != st_ivas->nchan_ism ) { +#ifdef DECODER_FORMAT_SWITCHING + if ( Opt_tsm ) + { + st_ivas->restartNeeded = 1; + + return IVAS_ERR_OK; + } + else + { +#endif #ifdef DEBUGGING - fprintf( stderr, "\nError: Changing the number of ISMs is not supported!\n" ); + fprintf( stderr, "\nError: Changing the number of ISMs is not supported!\n" ); +#endif + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Wrong number of objects signalled!" ); +#ifdef DECODER_FORMAT_SWITCHING + } #endif - return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Wrong number of objects signalled!" ); } st_ivas->nchan_ism = nchan_ism; @@ -268,10 +362,23 @@ ivas_error ivas_dec_get_format( if ( st_ivas->ini_frame > 0 && nchan_ism != st_ivas->nchan_ism ) { +#ifdef DECODER_FORMAT_SWITCHING + if ( Opt_tsm ) + { + st_ivas->restartNeeded = 1; + + return IVAS_ERR_OK; + } + else + { +#endif #ifdef DEBUGGING - fprintf( stderr, "\nError: Changing the number of ISMs is not supported!\n" ); + fprintf( stderr, "\nError: Changing the number of ISMs is not supported!\n" ); +#endif + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Wrong number of objects signalled!" ); +#ifdef DECODER_FORMAT_SWITCHING + } #endif - return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Wrong number of objects signalled!" ); } st_ivas->nchan_ism = nchan_ism; @@ -283,10 +390,23 @@ ivas_error ivas_dec_get_format( if ( st_ivas->ini_frame > 0 && nchan_ism != st_ivas->nchan_ism ) { +#ifdef DECODER_FORMAT_SWITCHING + if ( Opt_tsm ) + { + st_ivas->restartNeeded = 1; + + return IVAS_ERR_OK; + } + else + { +#endif #ifdef DEBUGGING - fprintf( stderr, "\nError: Changing the number of ISMs is not supported!\n" ); + fprintf( stderr, "\nError: Changing the number of ISMs is not supported!\n" ); +#endif + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Wrong number of objects signalled!" ); +#ifdef DECODER_FORMAT_SWITCHING + } #endif - return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Wrong number of objects signalled!" ); } st_ivas->nchan_ism = nchan_ism; @@ -310,10 +430,23 @@ ivas_error ivas_dec_get_format( if ( st_ivas->ini_frame > 0 && sba_order != st_ivas->sba_order ) { +#ifdef DECODER_FORMAT_SWITCHING + if ( Opt_tsm ) + { + st_ivas->restartNeeded = 1; + + return IVAS_ERR_OK; + } + else + { +#endif #ifdef DEBUGGING - fprintf( stderr, "\nError: Changing the SBA order is not supported!\n" ); + fprintf( stderr, "\nError: Changing the SBA order is not supported!\n" ); +#endif + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Wrong SBA order signalled!" ); +#ifdef DECODER_FORMAT_SWITCHING + } #endif - return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Wrong SBA order signalled!" ); } st_ivas->ism_mode = ivas_osba_ism_mode_select( ivas_total_brate, st_ivas->nchan_ism ); @@ -338,10 +471,23 @@ ivas_error ivas_dec_get_format( if ( st_ivas->ini_frame > 0 && st_ivas->transport_config != signaled_config ) { +#ifdef DECODER_FORMAT_SWITCHING + if ( Opt_tsm ) + { + st_ivas->restartNeeded = 1; + + return IVAS_ERR_OK; + } + else + { +#endif #ifdef DEBUGGING - fprintf( stderr, "\nError: Switching of MC configurations is not supported!\n" ); + fprintf( stderr, "\nError: Switching of MC configurations is not supported!\n" ); +#endif + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "wrong MC configuration signalled!" ); +#ifdef DECODER_FORMAT_SWITCHING + } #endif - return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "wrong MC configuration signalled!" ); } st_ivas->mc_mode = ivas_mc_mode_select( ivas_mc_map_output_config_to_mc_ls_setup( signaled_config ), st_ivas->hDecoderConfig->ivas_total_brate ); @@ -423,10 +569,23 @@ ivas_error ivas_dec_get_format( if ( st_ivas->ini_frame > 0 && nchan_ism != st_ivas->nchan_ism ) { +#ifdef DECODER_FORMAT_SWITCHING + if ( Opt_tsm ) + { + st_ivas->restartNeeded = 1; + + return IVAS_ERR_OK; + } + else + { +#endif #ifdef DEBUGGING - fprintf( stderr, "\nError: Changing the number of ISMs is not supported!\n" ); + fprintf( stderr, "\nError: Changing the number of ISMs is not supported!\n" ); +#endif + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Wrong number of objects signalled!" ); +#ifdef DECODER_FORMAT_SWITCHING + } #endif - return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Wrong number of objects signalled!" ); } st_ivas->nchan_ism = nchan_ism; @@ -1279,7 +1438,15 @@ ivas_error ivas_init_decoder( if ( output_config == IVAS_AUDIO_CONFIG_EXTERNAL ) { +#ifdef FIX_1419_MONO_STEREO_UMX + if ( st_ivas->ivas_format == MONO_FORMAT ) + { + hDecoderConfig->nchan_out = 1; + } + else if ( st_ivas->ivas_format == STEREO_FORMAT ) +#else if ( st_ivas->ivas_format == STEREO_FORMAT ) +#endif { hDecoderConfig->nchan_out = CPE_CHANNELS; } @@ -1332,6 +1499,13 @@ ivas_error ivas_init_decoder( st_ivas->hOutSetup.output_config = st_ivas->intern_config; st_ivas->hOutSetup.nchan_out_woLFE = audioCfg2channels( st_ivas->intern_config ); } +#ifdef FIX_1419_MONO_STEREO_UMX + + if ( st_ivas->ivas_format == MONO_FORMAT || st_ivas->ivas_format == STEREO_FORMAT ) + { + st_ivas->transport_config = ( st_ivas->ivas_format == MONO_FORMAT ) ? IVAS_AUDIO_CONFIG_MONO : IVAS_AUDIO_CONFIG_STEREO; + } +#endif /* Only initialize transport setup if it is used */ if ( st_ivas->transport_config != IVAS_AUDIO_CONFIG_INVALID ) @@ -1381,16 +1555,72 @@ ivas_error ivas_init_decoder( } } +#ifdef FIX_1318_ROOM_SIZE_CMD_LINE + /*--------------------------------------------------------------------------* + * Allocate and initialize HRTF Statistics handle, get default reverb values + *--------------------------------------------------------------------------*/ +#else /*--------------------------------------------------------------------* * Allocate and initialize HRTF Statistics handle *--------------------------------------------------------------------*/ +#endif if ( st_ivas->hOutSetup.output_config == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) { + /* Init HRTF statistics */ if ( ( error = ivas_HRTF_statistics_init( &st_ivas->hHrtfStatistics, output_Fs ) ) != IVAS_ERR_OK ) { return error; } +#ifdef FIX_1318_ROOM_SIZE_CMD_LINE + /* Get default reverb values based on format, if custom values were not given */ + if ( st_ivas->hDecoderConfig->Opt_RendConfigCustom == 0 ) + { + IVAS_DefaultReverbSize defaultReverbSize; + switch ( st_ivas->hDecoderConfig->Opt_RoomSize ) + { + case IVAS_ROOM_SIZE_AUTO: + switch ( st_ivas->ivas_format ) + { + case ISM_FORMAT: + defaultReverbSize = DEFAULT_REVERB_LARGE; + break; + case SBA_FORMAT: + defaultReverbSize = DEFAULT_REVERB_SMALL; + break; + case MASA_FORMAT: + defaultReverbSize = DEFAULT_REVERB_SMALL; + break; + case MC_FORMAT: + defaultReverbSize = DEFAULT_REVERB_MEDIUM; + break; + case MASA_ISM_FORMAT: + defaultReverbSize = DEFAULT_REVERB_MEDIUM; + break; + case SBA_ISM_FORMAT: + defaultReverbSize = DEFAULT_REVERB_MEDIUM; + break; + default: + defaultReverbSize = DEFAULT_REVERB_LARGE; + } + break; + case IVAS_ROOM_SIZE_SMALL: + defaultReverbSize = DEFAULT_REVERB_SMALL; + break; + case IVAS_ROOM_SIZE_MEDIUM: + defaultReverbSize = DEFAULT_REVERB_MEDIUM; + break; + case IVAS_ROOM_SIZE_LARGE: + default: + defaultReverbSize = DEFAULT_REVERB_LARGE; + break; + } + if ( ( error = ivas_render_config_change_defaults( st_ivas->hRenderConfig, defaultReverbSize ) ) != IVAS_ERR_OK ) + { + return error; + } + } +#endif } /*-----------------------------------------------------------------* @@ -1414,7 +1644,9 @@ ivas_error ivas_init_decoder( else if ( st_ivas->ivas_format == STEREO_FORMAT ) { st_ivas->nchan_transport = CPE_CHANNELS; +#ifndef FIX_1419_MONO_STEREO_UMX /* already set now by renderer_select() */ st_ivas->intern_config = IVAS_AUDIO_CONFIG_STEREO; +#endif st_ivas->nSCE = 0; st_ivas->nCPE = 1; /* in stereo, there is always only one CPE */ @@ -2308,7 +2540,8 @@ ivas_error ivas_init_decoder( } /*-----------------------------------------------------------------* - * LFE handles for rendering after rendering to adjust LFE delay to filter delay + * LFE handles for rendering after rendering to adjust LFE delay to + * filter delay *-----------------------------------------------------------------*/ if ( st_ivas->mc_mode == MC_MODE_MCT || st_ivas->mc_mode == MC_MODE_PARAMUPMIX ) @@ -2631,6 +2864,10 @@ void ivas_initialize_handles_dec( st_ivas->hRenderConfig = NULL; st_ivas->hExtOrientationData = NULL; st_ivas->hCombinedOrientationData = NULL; +#ifdef IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT + st_ivas->acousticEnvironmentsCount = 0; + st_ivas->pAcousticEnvironments = NULL; +#endif st_ivas->hSplitBinRend = NULL; for ( i = 0; i < MAX_HEAD_ROT_POSES - 1; ++i ) @@ -2852,6 +3089,15 @@ void ivas_destroy_dec( /* Config. Renderer */ ivas_render_config_close( &( st_ivas->hRenderConfig ) ); +#ifdef IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT + /* Acoustic environments */ + if ( st_ivas->pAcousticEnvironments != NULL ) + { + free( st_ivas->pAcousticEnvironments ); + st_ivas->pAcousticEnvironments = NULL; + } +#endif + /* Limiter struct */ ivas_limiter_close( &( st_ivas->hLimiter ) ); @@ -3140,6 +3386,7 @@ static ivas_error doSanityChecks_IVAS( return IVAS_ERROR( IVAS_ERR_INVALID_OUTPUT_FORMAT, "Error: Non-diegetic panning not supported in this IVAS format" ); } +#ifndef FIX_1419_MONO_STEREO_UMX /* we now support basically everything for stereo */ /* Verify stereo output configuration */ if ( st_ivas->ivas_format == STEREO_FORMAT ) { @@ -3152,10 +3399,26 @@ static ivas_error doSanityChecks_IVAS( else { if ( output_config == IVAS_AUDIO_CONFIG_INVALID ) +#else /* exclude invalid configs instead of matching valid ones */ + if ( output_config == IVAS_AUDIO_CONFIG_INVALID || + output_config == IVAS_AUDIO_CONFIG_ISM1 || + output_config == IVAS_AUDIO_CONFIG_ISM2 || + output_config == IVAS_AUDIO_CONFIG_ISM3 || + output_config == IVAS_AUDIO_CONFIG_ISM4 || + output_config == IVAS_AUDIO_CONFIG_MASA1 || + output_config == IVAS_AUDIO_CONFIG_MASA2 ) +#endif { return IVAS_ERROR( IVAS_ERR_INVALID_OUTPUT_FORMAT, "Incorrect output configuration specified!" ); } + if ( ( st_ivas->ivas_format == MONO_FORMAT || st_ivas->ivas_format == STEREO_FORMAT ) && + ( output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) + { + return IVAS_ERROR( IVAS_ERR_INVALID_OUTPUT_FORMAT, "Incorrect output configuration specified!" ); + } +#ifndef FIX_1419_MONO_STEREO_UMX } +#endif if ( ( output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) && output_Fs != 48000 ) { diff --git a/lib_dec/ivas_ism_renderer.c b/lib_dec/ivas_ism_renderer.c index 11d797253aa423b253950e3707bf6404e9e97e93..38ef231629a03754352245eedba06d3d9ba29c72 100644 --- a/lib_dec/ivas_ism_renderer.c +++ b/lib_dec/ivas_ism_renderer.c @@ -301,7 +301,9 @@ void ivas_ism_get_stereo_gains( { float aziRad, eleRad; float y, mappedX, aziRadMapped, A, A2, A3; +#ifndef NONBE_FIX_1426_STEREO_PANNING_BETWEEN_OPT_LEVEL const float LsAngleRad = 30.0f * PI_OVER_180; +#endif /* Convert azi and ele to an azi value of the cone of confusion */ aziRad = azimuth * PI_OVER_180; @@ -311,19 +313,31 @@ void ivas_ism_get_stereo_gains( aziRadMapped = atan2f( y, mappedX ); /* Determine the amplitude panning gains */ +#ifdef NONBE_FIX_1426_STEREO_PANNING_BETWEEN_OPT_LEVEL + if ( aziRadMapped >= LS_ANGLE_RAD_30_DEG ) +#else if ( aziRadMapped >= LsAngleRad ) +#endif { /* Left side */ *left_gain = 1.0f; *right_gain = 0.0f; } +#ifdef NONBE_FIX_1426_STEREO_PANNING_BETWEEN_OPT_LEVEL + else if ( aziRadMapped <= -LS_ANGLE_RAD_30_DEG ) +#else else if ( aziRadMapped <= -LsAngleRad ) +#endif { /* Right side */ *left_gain = 0.0f; *right_gain = 1.0f; } else /* Tangent panning law */ { +#ifdef NONBE_FIX_1426_STEREO_PANNING_BETWEEN_OPT_LEVEL + A = tanf( aziRadMapped ) * INV_TAN_LS_ANGLE_RAD_30_DEG; +#else A = tanf( aziRadMapped ) / tanf( LsAngleRad ); +#endif A2 = ( A - 1.0f ) / max( 0.001f, A + 1.0f ); A3 = 1.0f / ( A2 * A2 + 1.0f ); *left_gain = sqrtf( A3 ); diff --git a/lib_dec/ivas_jbm_dec.c b/lib_dec/ivas_jbm_dec.c index 570deda672dfa151403416de74b831b050b9a1e4..7bf613e70a60224f8be7e1817c8aa3c67b1e071e 100644 --- a/lib_dec/ivas_jbm_dec.c +++ b/lib_dec/ivas_jbm_dec.c @@ -937,14 +937,44 @@ ivas_error ivas_jbm_dec_render( { ivas_jbm_dec_tc_buffer_playout( st_ivas, nSamplesAskedLocal, nSamplesRendered, p_output ); } +#ifdef FIX_1419_MONO_STEREO_UMX + else if ( st_ivas->ivas_format == MONO_FORMAT || st_ivas->ivas_format == STEREO_FORMAT ) +#else else if ( st_ivas->ivas_format == STEREO_FORMAT ) +#endif { +#ifdef FIX_1419_MONO_STEREO_UMX + *nSamplesRendered = min( st_ivas->hTcBuffer->n_samples_available, nSamplesAskedLocal ); +#endif + /* Rendering */ if ( st_ivas->renderer_type == RENDERER_MC ) { +#ifndef FIX_1419_MONO_STEREO_UMX *nSamplesRendered = min( st_ivas->hTcBuffer->n_samples_available, nSamplesAskedLocal ); +#endif ivas_ls_setup_conversion( st_ivas, st_ivas->nchan_transport, *nSamplesRendered, p_tc, p_output ); } +#ifdef FIX_1419_MONO_STEREO_UMX + else if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) + { + if ( st_ivas->ivas_format == MONO_FORMAT ) + { + /* routed to W */ + ivas_jbm_dec_tc_buffer_playout( st_ivas, nSamplesAskedLocal, nSamplesRendered, p_output ); + } + else if ( st_ivas->ivas_format == STEREO_FORMAT ) + { + for ( n = 0; n < *nSamplesRendered; n++ ) + { + float tmp; + tmp = p_output[0][n]; + p_output[0][n] = 0.5f * ( tmp + p_output[1][n] ); /* W = 0.5 * ( L + R ) */ + p_output[1][n] = 0.5f * ( tmp - p_output[1][n] ); /* Y = 0.5 * ( L - R ) */ + } + } + } +#endif /* FIX_1419_MONO_STEREO_UMX */ } else if ( st_ivas->ivas_format == ISM_FORMAT ) { @@ -1931,11 +1961,15 @@ int16_t ivas_jbm_dec_get_num_tc_channels( ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; +#ifndef FIX_1419_MONO_STEREO_UMX /* since we support more output formats for mono, this is no longer sensible; leave it at the default from above */ if ( st_ivas->ivas_format == MONO_FORMAT ) { num_tc = st_ivas->hDecoderConfig->nchan_out; } else if ( st_ivas->ivas_format == STEREO_FORMAT && st_ivas->hDecoderConfig->nchan_out == 1 ) +#else + if ( st_ivas->ivas_format == STEREO_FORMAT && st_ivas->hDecoderConfig->nchan_out == 1 ) +#endif { num_tc = 1; } @@ -2803,7 +2837,11 @@ void ivas_dec_prepare_renderer( ivas_omasa_gain_masa_tc( st_ivas->hTcBuffer->tc, st_ivas->hMasaIsmData->gain_masa_edited, st_ivas->nchan_ism, st_ivas->hTcBuffer->n_samples_available ); } } +#ifdef FIX_1419_MONO_STEREO_UMX + else if ( st_ivas->ivas_format == MONO_FORMAT || st_ivas->ivas_format == STEREO_FORMAT ) +#else else if ( st_ivas->ivas_format == STEREO_FORMAT ) +#endif { ivas_jbm_dec_td_renderers_adapt_subframes( st_ivas ); } diff --git a/lib_dec/ivas_mdct_core_dec.c b/lib_dec/ivas_mdct_core_dec.c index 9cf401aba420831ffb4701c627136ca1345cb345..83e69cc96b10ae097cd93e38ad1ccce34c37d067 100644 --- a/lib_dec/ivas_mdct_core_dec.c +++ b/lib_dec/ivas_mdct_core_dec.c @@ -160,6 +160,13 @@ static void dec_prm_tcx_sidebits( st->last_core_from_bs = st->last_core; } +#ifdef FIX_BASOP_ISSUE_1585_CUT_BS_CRASH + /* for first frame reset last_core to initialization value for better error-robustness*/ + if ( st->ini_frame == 0 ) + { + st->last_core = TCX_20_CORE; + } +#endif getTCXWindowing( st->core, st->last_core, st->element_mode, st->hTcxCfg, st0 ); st->hTcxDec->kernel_type[0] = st->hTcxDec->kernel_type[1] = MDCT_IV; diff --git a/lib_dec/ivas_output_config.c b/lib_dec/ivas_output_config.c index b4b241815dd11075e142dd2a595cfa0935b692c3..f5b4d577b1ab0f58370f02427ef03f71fa49f325 100644 --- a/lib_dec/ivas_output_config.c +++ b/lib_dec/ivas_output_config.c @@ -41,6 +41,28 @@ #endif #include "wmc_auto.h" +#ifdef FIX_1419_MONO_STEREO_UMX + +static void ms_bin_upmix_renderer_select( + const IVAS_FORMAT ivas_format, /* i : Decoder format */ + IVAS_AUDIO_CONFIG *internal_config, /* o : Internal configuration for rendering */ + RENDERER_TYPE *renderer_type /* o : Selected renderer type */ +) +{ + + *internal_config = ( ivas_format == MONO_FORMAT ) ? IVAS_AUDIO_CONFIG_MONO : IVAS_AUDIO_CONFIG_STEREO; + + if ( ivas_format == MONO_FORMAT ) + { + *renderer_type = RENDERER_NON_DIEGETIC_DOWNMIX; + } + else + { + *renderer_type = RENDERER_DISABLE; + } + return; +} +#endif /*-------------------------------------------------------------------------* * ivas_renderer_select() @@ -82,7 +104,17 @@ void ivas_renderer_select( if ( output_config == IVAS_AUDIO_CONFIG_BINAURAL || output_config == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR || output_config == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB || output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) { +#ifdef FIX_1419_MONO_STEREO_UMX + if ( st_ivas->ivas_format == MONO_FORMAT || st_ivas->ivas_format == STEREO_FORMAT ) + { + ms_bin_upmix_renderer_select( st_ivas->ivas_format, + internal_config, + renderer_type ); + } + else if ( st_ivas->ivas_format == ISM_FORMAT ) +#else if ( st_ivas->ivas_format == ISM_FORMAT ) +#endif { if ( st_ivas->ism_mode == ISM_MODE_PARAM ) { @@ -252,6 +284,45 @@ void ivas_renderer_select( * Non-binaural rendering configurations *-----------------------------------------------------------------*/ +#ifdef FIX_1419_MONO_STEREO_UMX + else if ( st_ivas->ivas_format == MONO_FORMAT || st_ivas->ivas_format == STEREO_FORMAT ) + { + *internal_config = ( st_ivas->ivas_format == MONO_FORMAT ) ? IVAS_AUDIO_CONFIG_MONO : IVAS_AUDIO_CONFIG_STEREO; + switch ( output_config ) + { + case IVAS_AUDIO_CONFIG_FOA: + case IVAS_AUDIO_CONFIG_HOA2: + case IVAS_AUDIO_CONFIG_HOA3: + *renderer_type = RENDERER_SBA_LINEAR_ENC; + break; + case IVAS_AUDIO_CONFIG_5_1: + case IVAS_AUDIO_CONFIG_7_1: + case IVAS_AUDIO_CONFIG_5_1_2: + case IVAS_AUDIO_CONFIG_5_1_4: + case IVAS_AUDIO_CONFIG_7_1_4: + case IVAS_AUDIO_CONFIG_LS_CUSTOM: + *renderer_type = RENDERER_MC; + break; + case IVAS_AUDIO_CONFIG_MONO: + if ( *internal_config == IVAS_AUDIO_CONFIG_STEREO ) + { + /* stereo to mono downmix */ + *renderer_type = RENDERER_MC; + } + break; + case IVAS_AUDIO_CONFIG_STEREO: + if ( *internal_config == IVAS_AUDIO_CONFIG_MONO ) + { + /* mono to stereo upmix */ + *renderer_type = RENDERER_NON_DIEGETIC_DOWNMIX; + } + break; + default: + /* RENDERER_DISABLE already set by default */ + break; + } + } +#else else if ( st_ivas->ivas_format == MONO_FORMAT ) { if ( output_config == IVAS_AUDIO_CONFIG_STEREO ) @@ -266,6 +337,7 @@ void ivas_renderer_select( *renderer_type = RENDERER_MC; } } +#endif else if ( st_ivas->ivas_format == ISM_FORMAT ) { if ( ( output_config == IVAS_AUDIO_CONFIG_STEREO ) && ( st_ivas->hDecoderConfig->Opt_non_diegetic_pan ) ) diff --git a/lib_dec/ivas_sba_dirac_stereo_dec.c b/lib_dec/ivas_sba_dirac_stereo_dec.c index 52262a9e8fe2af2205b2146115a6dc6e45651467..b20afdca419156bd75d5b8aa574f5f803d49d379 100644 --- a/lib_dec/ivas_sba_dirac_stereo_dec.c +++ b/lib_dec/ivas_sba_dirac_stereo_dec.c @@ -187,8 +187,9 @@ static float get_panning( { float aziRad, eleRad, y, mappedX, aziRadMapped, panning; float A, A2, A3; +#ifndef NONBE_FIX_1426_STEREO_PANNING_BETWEEN_OPT_LEVEL const float LsAngleRad = 30.0f * PI_OVER_180; - +#endif aziRad = aziDeg * PI_OVER_180; eleRad = eleDeg * PI_OVER_180; y = ( sinf( aziRad ) * cosf( eleRad ) ); @@ -197,17 +198,29 @@ static float get_panning( /* Determine the real valued amplitude panning gains */ panning = 0.0f; +#ifdef NONBE_FIX_1426_STEREO_PANNING_BETWEEN_OPT_LEVEL + if ( aziRadMapped >= LS_ANGLE_RAD_30_DEG ) +#else if ( aziRadMapped >= LsAngleRad ) +#endif { /* Left side */ panning = 1.0f; } +#ifdef NONBE_FIX_1426_STEREO_PANNING_BETWEEN_OPT_LEVEL + else if ( aziRadMapped <= -LS_ANGLE_RAD_30_DEG ) +#else else if ( aziRadMapped <= -LsAngleRad ) +#endif { /* Right side */ panning = -1.0f; } else /* Tangent panning law */ { +#ifdef NONBE_FIX_1426_STEREO_PANNING_BETWEEN_OPT_LEVEL + A = tanf( aziRadMapped ) * INV_TAN_LS_ANGLE_RAD_30_DEG; +#else A = tanf( aziRadMapped ) / tanf( LsAngleRad ); +#endif A2 = ( A - 1.0f ) / max( 0.001f, A + 1.0f ); A3 = 1.0f / ( A2 * A2 + 1.0f ); panning = 2 * A3 - 1.0f; diff --git a/lib_dec/ivas_stat_dec.h b/lib_dec/ivas_stat_dec.h index f1efb32a1019670330be0bc7f647dbadc404a0d3..6b6a99b32bb24df1c2a37acaae707040346263fe 100644 --- a/lib_dec/ivas_stat_dec.h +++ b/lib_dec/ivas_stat_dec.h @@ -1007,15 +1007,18 @@ typedef struct jbm_metadata_structure typedef struct decoder_config_structure { - int32_t ivas_total_brate; /* IVAS total bitrate in bps */ - int32_t last_ivas_total_brate; /* last IVAS total bitrate in bps */ - int32_t output_Fs; /* output signal sampling frequency in Hz */ - int16_t nchan_out; /* number of output audio channels */ - AUDIO_CONFIG output_config; /* output audio configuration */ - int16_t Opt_LsCustom; /* indicates whether loudspeaker custom setup is used */ - int16_t Opt_HRTF_binary; /* indicates whether HRTF binary file is used */ - int16_t Opt_Headrotation; /* indicates whether head-rotation is used */ - int16_t Opt_RendConfigCustom; /* indicates whether Renderer configuration custom setup is used */ + int32_t ivas_total_brate; /* IVAS total bitrate in bps */ + int32_t last_ivas_total_brate; /* last IVAS total bitrate in bps */ + int32_t output_Fs; /* output signal sampling frequency in Hz */ + int16_t nchan_out; /* number of output audio channels */ + AUDIO_CONFIG output_config; /* output audio configuration */ + int16_t Opt_LsCustom; /* indicates whether loudspeaker custom setup is used */ + int16_t Opt_HRTF_binary; /* indicates whether HRTF binary file is used */ + int16_t Opt_Headrotation; /* indicates whether head-rotation is used */ + int16_t Opt_RendConfigCustom; /* indicates whether Renderer configuration custom setup is used */ +#ifdef FIX_1318_ROOM_SIZE_CMD_LINE + IVAS_ROOM_SIZE_T Opt_RoomSize; /* Selected room size */ +#endif IVAS_HEAD_ORIENT_TRK_T orientation_tracking; /* indicates orientation tracking type */ int16_t Opt_non_diegetic_pan; /* indicates diegetic or not */ float non_diegetic_pan_gain; /* non diegetic panning gain*/ @@ -1128,6 +1131,10 @@ typedef struct Decoder_Struct MASA_ISM_DATA_HANDLE hMasaIsmData; /* OMASA rendering handle */ SBA_ISM_DATA_HANDLE hSbaIsmData; /* OSBA rendering handle */ +#ifdef IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT + IVAS_ROOM_ACOUSTICS_CONFIG_DATA *pAcousticEnvironments; /* Acoustic environment array */ + uint16_t acousticEnvironmentsCount; /* Number of acoustic environments in the array*/ +#endif int16_t flag_omasa_brate; ISAR_DEC_SPLIT_REND_WRAPPER_HANDLE hSplitBinRend; /* ISAR split binaural rendering handle */ @@ -1147,6 +1154,9 @@ typedef struct Decoder_Struct #ifdef TMP_1342_WORKAROUND_DEC_FLUSH_BROKEN_IN_SR int16_t flushing; #endif +#ifdef DECODER_FORMAT_SWITCHING + int16_t restartNeeded; /* Flag to signal decoder restart */ +#endif } Decoder_Struct; diff --git a/lib_dec/lib_dec.c b/lib_dec/lib_dec.c index ff312ddfe416163aa791761b8eaab1fcf6f5c4c6..de95304301e1510ec565a371d2c06fd03f1f0d1c 100644 --- a/lib_dec/lib_dec.c +++ b/lib_dec/lib_dec.c @@ -41,6 +41,9 @@ #include "jbm_jb4sb.h" #include "jbm_pcmdsp_apa.h" #include "jbm_pcmdsp_fifo.h" +#ifdef IVAS_RTPDUMP +#include "ivas_rtp_pi_data.h" +#endif #include #include #ifdef DEBUGGING @@ -222,6 +225,10 @@ ivas_error IVAS_DEC_Open( /* initialize pointers to handles to NULL */ ivas_initialize_handles_dec( st_ivas ); +#ifdef DECODER_FORMAT_SWITCHING + st_ivas->restartNeeded = 0; +#endif + /* set high-level parameters */ if ( mode == IVAS_DEC_MODE_EVS ) { @@ -310,6 +317,9 @@ static void init_decoder_config( hDecoderConfig->Opt_HRTF_binary = 0; hDecoderConfig->Opt_Headrotation = 0; hDecoderConfig->Opt_RendConfigCustom = 0; +#ifdef FIX_1318_ROOM_SIZE_CMD_LINE + hDecoderConfig->Opt_RoomSize = IVAS_ROOM_SIZE_AUTO; +#endif hDecoderConfig->orientation_tracking = IVAS_HEAD_ORIENT_TRK_NONE; hDecoderConfig->Opt_non_diegetic_pan = 0; hDecoderConfig->non_diegetic_pan_gain = 0; @@ -452,12 +462,15 @@ ivas_error IVAS_DEC_Configure( const bool enableExternalOrientation, /* i : enable external orientations */ const IVAS_HEAD_ORIENT_TRK_T orientation_tracking, /* i : head orientation tracking type */ const bool renderConfigEnabled, /* i : enable Renderer config. file for binaural output */ - const bool non_diegetic_pan_enabled, /* i : enabled diegetic panning */ - const float non_diegetic_pan_gain, /* i : non diegetic panning gain */ - const bool dpidEnabled, /* i : enable directivity pattern option */ - const uint16_t acousticEnvironmentId, /* i : Acoustic environment ID */ - const bool objEditEnabled, /* i : enable object editing */ - const bool delayCompensationEnabled /* i : enable delay compensation */ +#ifdef FIX_1318_ROOM_SIZE_CMD_LINE + const IVAS_ROOM_SIZE_T roomSize, /* i : room size selector for reverb */ +#endif + const bool non_diegetic_pan_enabled, /* i : enabled diegetic panning */ + const float non_diegetic_pan_gain, /* i : non diegetic panning gain */ + const bool dpidEnabled, /* i : enable directivity pattern option */ + const uint16_t acousticEnvironmentId, /* i : Acoustic environment ID */ + const bool objEditEnabled, /* i : enable object editing */ + const bool delayCompensationEnabled /* i : enable delay compensation */ ) { Decoder_Struct *st_ivas; @@ -474,8 +487,21 @@ ivas_error IVAS_DEC_Configure( return IVAS_ERR_WRONG_PARAMS; } +#ifdef FIX_1419_MONO_STEREO_UMX + if ( hIvasDec->mode == IVAS_DEC_MODE_EVS && + ( outputConfig == IVAS_AUDIO_CONFIG_INVALID || + outputConfig == IVAS_AUDIO_CONFIG_ISM1 || + outputConfig == IVAS_AUDIO_CONFIG_ISM2 || + outputConfig == IVAS_AUDIO_CONFIG_ISM3 || + outputConfig == IVAS_AUDIO_CONFIG_ISM4 || + outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || + outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM || + outputConfig == IVAS_AUDIO_CONFIG_MASA1 || + outputConfig == IVAS_AUDIO_CONFIG_MASA2 ) ) +#else /* we now support all output formats, so this validation is redundant */ if ( hIvasDec->mode == IVAS_DEC_MODE_EVS && !( ( outputConfig == IVAS_AUDIO_CONFIG_MONO && !non_diegetic_pan_enabled ) || ( outputConfig == IVAS_AUDIO_CONFIG_STEREO && non_diegetic_pan_enabled ) ) ) +#endif { return IVAS_ERR_WRONG_MODE; } @@ -508,6 +534,9 @@ ivas_error IVAS_DEC_Configure( hDecoderConfig->orientation_tracking = orientation_tracking; hDecoderConfig->Opt_HRTF_binary = (int16_t) hrtfReaderEnabled; hDecoderConfig->Opt_RendConfigCustom = (int16_t) renderConfigEnabled; +#ifdef FIX_1318_ROOM_SIZE_CMD_LINE + hDecoderConfig->Opt_RoomSize = roomSize; +#endif hDecoderConfig->Opt_non_diegetic_pan = (int16_t) non_diegetic_pan_enabled; hDecoderConfig->non_diegetic_pan_gain = non_diegetic_pan_gain; hDecoderConfig->Opt_delay_comp = (int16_t) delayCompensationEnabled; @@ -1002,7 +1031,9 @@ ivas_error IVAS_DEC_ReadFormat( { ivas_error error; Decoder_Struct *st_ivas; +#ifndef DECODER_FORMAT_SWITCHING IVAS_FORMAT ivas_format_old; +#endif ISM_MODE ism_mode_old; MC_MODE mc_mode_old; int16_t nchan_transport_old; @@ -1015,7 +1046,9 @@ ivas_error IVAS_DEC_ReadFormat( } st_ivas = hIvasDec->st_ivas; +#ifndef DECODER_FORMAT_SWITCHING ivas_format_old = st_ivas->ivas_format; +#endif ism_mode_old = st_ivas->ism_mode; mc_mode_old = st_ivas->mc_mode; nchan_transport_old = st_ivas->nchan_transport; @@ -1038,10 +1071,17 @@ ivas_error IVAS_DEC_ReadFormat( return error; } +#ifdef DECODER_FORMAT_SWITCHING + if ( st_ivas->restartNeeded == 1 ) + { + return IVAS_ERR_OK; + } +#else if ( ivas_format_old != st_ivas->ivas_format && st_ivas->ini_frame > 0 && !( st_ivas->ivas_format == MASA_FORMAT || st_ivas->ivas_format == MASA_ISM_FORMAT ) ) { return ( IVAS_ERROR( IVAS_ERR_INVALID_INPUT_FORMAT, "IVAS format switching is not allowed." ) ); } +#endif /* Select binaural renderer */ ivas_renderer_select( st_ivas ); @@ -1515,13 +1555,35 @@ ivas_error IVAS_DEC_SetEditableParameters( st_ivas->hIsmMetaData[obj]->edited_radius = hIvasEditableParameters.ism_metadata[obj].radius; st_ivas->hIsmMetaData[obj]->edited_yaw = hIvasEditableParameters.ism_metadata[obj].yaw; st_ivas->hIsmMetaData[obj]->edited_pitch = hIvasEditableParameters.ism_metadata[obj].pitch; +#ifdef FIX_GAIN_EDIT_LIMITS + if ( hIvasEditableParameters.ism_metadata[obj].gain > EDIT_GAIN_MAX ) + { + st_ivas->hIsmMetaData[obj]->edited_gain = EDIT_GAIN_MAX; + } + else + { + st_ivas->hIsmMetaData[obj]->edited_gain = hIvasEditableParameters.ism_metadata[obj].gain; + } +#else st_ivas->hIsmMetaData[obj]->edited_gain = hIvasEditableParameters.ism_metadata[obj].gain; +#endif st_ivas->hIsmMetaData[obj]->non_diegetic_flag = hIvasEditableParameters.ism_metadata[obj].non_diegetic_flag; } if ( ism_mode == ISM_SBA_MODE_DISC ) { +#ifdef FIX_GAIN_EDIT_LIMITS + if ( hIvasEditableParameters.gain_bed > EDIT_GAIN_MAX ) + { + st_ivas->hSbaIsmData->gain_bed = EDIT_GAIN_MAX; + } + else + { + st_ivas->hSbaIsmData->gain_bed = hIvasEditableParameters.gain_bed; + } +#else st_ivas->hSbaIsmData->gain_bed = hIvasEditableParameters.gain_bed; +#endif } } else if ( ism_mode == ISM_MODE_PARAM ) @@ -1536,7 +1598,23 @@ ivas_error IVAS_DEC_SetEditableParameters( if ( st_ivas->hMasaIsmData != NULL ) { +#ifdef FIX_GAIN_EDIT_LIMITS + /* Limit gain edit to a range of +12dB to -24dB with parametric ISM mode */ + if ( hIvasEditableParameters.ism_metadata[obj].gain > EDIT_GAIN_MAX ) + { + st_ivas->hMasaIsmData->gain_ism_edited[obj] = EDIT_GAIN_MAX; + } + else if ( hIvasEditableParameters.ism_metadata[obj].gain < EDIT_GAIN_MIN ) + { + st_ivas->hMasaIsmData->gain_ism_edited[obj] = EDIT_GAIN_MIN; + } + else + { + st_ivas->hMasaIsmData->gain_ism_edited[obj] = hIvasEditableParameters.ism_metadata[obj].gain; + } +#else st_ivas->hMasaIsmData->gain_ism_edited[obj] = hIvasEditableParameters.ism_metadata[obj].gain; +#endif /* Detect direction editing in Param-ISM mode */ if ( fabsf( st_ivas->hParamIsmDec->azimuth_values[obj] - hIvasEditableParameters.ism_metadata[obj].azimuth ) > OMASA_AZI_EDIT_THR || @@ -1670,7 +1748,23 @@ ivas_error IVAS_DEC_SetEditableParameters( if ( fabsf( st_ivas->hIsmMetaData[obj]->edited_gain - hIvasEditableParameters.ism_metadata[obj].gain ) > OMASA_GAIN_EDIT_THR ) { st_ivas->hMasaIsmData->ism_gain_is_edited[obj] = 1u; +#ifdef FIX_GAIN_EDIT_LIMITS + /* Limit masa gain edit to a range of +12dB to -infdB with discrete OMASA mode and +12dB to -24dB with parametric OMASA mode */ + if ( hIvasEditableParameters.ism_metadata[obj].gain > EDIT_GAIN_MAX ) + { + st_ivas->hMasaIsmData->gain_ism_edited[obj] = EDIT_GAIN_MAX; + } + else if ( ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ && hIvasEditableParameters.ism_metadata[obj].gain < EDIT_GAIN_MIN ) + { + st_ivas->hMasaIsmData->gain_ism_edited[obj] = EDIT_GAIN_MIN; + } + else + { + st_ivas->hMasaIsmData->gain_ism_edited[obj] = hIvasEditableParameters.ism_metadata[obj].gain; + } +#else st_ivas->hMasaIsmData->gain_ism_edited[obj] = hIvasEditableParameters.ism_metadata[obj].gain; +#endif } else { @@ -1683,17 +1777,57 @@ ivas_error IVAS_DEC_SetEditableParameters( { st_ivas->hIsmMetaData[obj]->edited_azimuth = hIvasEditableParameters.ism_metadata[obj].azimuth; st_ivas->hIsmMetaData[obj]->edited_elevation = hIvasEditableParameters.ism_metadata[obj].elevation; +#ifdef FIX_1427_OBJ_EDITING_EXT_METADATA // Disable editing extended metadata for OMASA Param ISM + if ( ism_mode == ISM_MASA_MODE_DISC ) + { + st_ivas->hIsmMetaData[obj]->edited_yaw = hIvasEditableParameters.ism_metadata[obj].yaw; + st_ivas->hIsmMetaData[obj]->edited_pitch = hIvasEditableParameters.ism_metadata[obj].pitch; + st_ivas->hIsmMetaData[obj]->edited_radius = hIvasEditableParameters.ism_metadata[obj].radius; + } +#else st_ivas->hIsmMetaData[obj]->edited_yaw = hIvasEditableParameters.ism_metadata[obj].yaw; st_ivas->hIsmMetaData[obj]->edited_pitch = hIvasEditableParameters.ism_metadata[obj].pitch; st_ivas->hIsmMetaData[obj]->edited_radius = hIvasEditableParameters.ism_metadata[obj].radius; +#endif +#ifdef FIX_GAIN_EDIT_LIMITS + if ( hIvasEditableParameters.ism_metadata[obj].gain > EDIT_GAIN_MAX ) + { + st_ivas->hIsmMetaData[obj]->edited_gain = EDIT_GAIN_MAX; + } + else if ( ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ && hIvasEditableParameters.ism_metadata[obj].gain < EDIT_GAIN_MIN ) + { + st_ivas->hIsmMetaData[obj]->edited_gain = EDIT_GAIN_MIN; + } + else + { + st_ivas->hIsmMetaData[obj]->edited_gain = hIvasEditableParameters.ism_metadata[obj].gain; + } +#else st_ivas->hIsmMetaData[obj]->edited_gain = hIvasEditableParameters.ism_metadata[obj].gain; +#endif st_ivas->hIsmMetaData[obj]->non_diegetic_flag = hIvasEditableParameters.ism_metadata[obj].non_diegetic_flag; } } if ( fabsf( hIvasEditableParameters.gain_bed - 1.0f ) > OMASA_GAIN_EDIT_THR ) { +#ifdef FIX_GAIN_EDIT_LIMITS + /* Limit masa gain edit to a range of +12dB to -infdB with discrete OMASA mode and +12dB to -24dB with parametric OMASA mode */ + if ( hIvasEditableParameters.gain_bed > EDIT_GAIN_MAX ) + { + st_ivas->hMasaIsmData->gain_masa_edited = EDIT_GAIN_MAX; + } + else if ( ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ && hIvasEditableParameters.gain_bed < EDIT_GAIN_MIN ) + { + st_ivas->hMasaIsmData->gain_masa_edited = EDIT_GAIN_MIN; + } + else + { + st_ivas->hMasaIsmData->gain_masa_edited = hIvasEditableParameters.gain_bed; + } +#else st_ivas->hMasaIsmData->gain_masa_edited = hIvasEditableParameters.gain_bed; +#endif st_ivas->hMasaIsmData->masa_gain_is_edited = 1u; } else @@ -2489,10 +2623,20 @@ ivas_error IVAS_DEC_GetFormat( *format = IVAS_DEC_BS_UNKOWN; } +#ifdef DECODER_FORMAT_SWITCHING + if ( *format == IVAS_DEC_BS_MASA && hIvasDec->st_ivas->hMasa != NULL ) + { + if ( hIvasDec->st_ivas->hMasa->config.input_ivas_format == MASA_ISM_FORMAT ) + { + *format = IVAS_DEC_BS_MASA_ISM; + } + } +#else if ( *format == IVAS_DEC_BS_MASA && hIvasDec->st_ivas->hMasa->config.input_ivas_format == MASA_ISM_FORMAT ) { *format = IVAS_DEC_BS_MASA_ISM; } +#endif return IVAS_ERR_OK; } @@ -3177,6 +3321,184 @@ ivas_error IVAS_DEC_HRTF_binary_close( } +#ifdef IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT +/*---------------------------------------------------------------------* + * IVAS_DEC_AddAcousticEnvironment( ) + * + * Adds acoustic environment configuration + *---------------------------------------------------------------------*/ + +ivas_error IVAS_DEC_AddAcousticEnvironment( + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + const IVAS_ROOM_ACOUSTICS_CONFIG_DATA roomAcousticsConfig /* i : Room acoustic configuration */ +) +{ + uint16_t n; + Decoder_Struct *st_ivas; + IVAS_ROOM_ACOUSTICS_CONFIG_DATA *pAE = NULL; + + if ( hIvasDec == NULL || hIvasDec->st_ivas == NULL || ( hIvasDec->st_ivas->acousticEnvironmentsCount > 0 && hIvasDec->st_ivas->pAcousticEnvironments == NULL ) ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + st_ivas = hIvasDec->st_ivas; + + /* Check if already there */ + for ( n = 0; n < st_ivas->acousticEnvironmentsCount; n++ ) + { + if ( st_ivas->pAcousticEnvironments[n].aeID == roomAcousticsConfig.aeID ) + { + pAE = &st_ivas->pAcousticEnvironments[n]; + break; + } + } + + /* If not found */ + if ( pAE == NULL ) + { + IVAS_ROOM_ACOUSTICS_CONFIG_DATA *ppAE = malloc( ( st_ivas->acousticEnvironmentsCount + 1 ) * sizeof( IVAS_ROOM_ACOUSTICS_CONFIG_DATA ) ); + + if ( ppAE == NULL ) + { + return IVAS_ERR_FAILED_ALLOC; + } + + for ( n = 0; n < st_ivas->acousticEnvironmentsCount; n++ ) + { + pAE = &ppAE[n]; + pAE->aeID = st_ivas->pAcousticEnvironments[n].aeID; + pAE->nBands = st_ivas->pAcousticEnvironments[n].nBands; + pAE->acousticPreDelay = st_ivas->pAcousticEnvironments[n].acousticPreDelay; + pAE->inputPreDelay = st_ivas->pAcousticEnvironments[n].inputPreDelay; + + mvr2r( st_ivas->pAcousticEnvironments[n].pFc_input, pAE->pFc_input, CLDFB_NO_CHANNELS_MAX ); + mvr2r( st_ivas->pAcousticEnvironments[n].pAcoustic_rt60, pAE->pAcoustic_rt60, CLDFB_NO_CHANNELS_MAX ); + mvr2r( st_ivas->pAcousticEnvironments[n].pAcoustic_dsr, pAE->pAcoustic_dsr, CLDFB_NO_CHANNELS_MAX ); + + pAE->use_er = st_ivas->pAcousticEnvironments[n].use_er; + + if ( pAE->use_er == 1 ) + { + pAE->lowComplexity = st_ivas->pAcousticEnvironments[n].lowComplexity; + pAE->dimensions.x = st_ivas->pAcousticEnvironments[n].dimensions.x; + pAE->dimensions.y = st_ivas->pAcousticEnvironments[n].dimensions.y; + pAE->dimensions.z = st_ivas->pAcousticEnvironments[n].dimensions.z; + pAE->ListenerOrigin.x = st_ivas->pAcousticEnvironments[n].ListenerOrigin.x; + pAE->ListenerOrigin.y = st_ivas->pAcousticEnvironments[n].ListenerOrigin.y; + pAE->ListenerOrigin.z = st_ivas->pAcousticEnvironments[n].ListenerOrigin.z; + + mvr2r( st_ivas->pAcousticEnvironments[n].AbsCoeff, pAE->AbsCoeff, IVAS_ROOM_ABS_COEFF ); + } + } + + free( st_ivas->pAcousticEnvironments ); + st_ivas->pAcousticEnvironments = ppAE; + n = st_ivas->acousticEnvironmentsCount++; + pAE = &st_ivas->pAcousticEnvironments[n]; + } + + pAE->aeID = roomAcousticsConfig.aeID; + pAE->nBands = roomAcousticsConfig.nBands; + pAE->acousticPreDelay = roomAcousticsConfig.acousticPreDelay; + pAE->inputPreDelay = roomAcousticsConfig.inputPreDelay; + + mvr2r( roomAcousticsConfig.pFc_input, pAE->pFc_input, CLDFB_NO_CHANNELS_MAX ); + mvr2r( roomAcousticsConfig.pAcoustic_rt60, pAE->pAcoustic_rt60, CLDFB_NO_CHANNELS_MAX ); + mvr2r( roomAcousticsConfig.pAcoustic_dsr, pAE->pAcoustic_dsr, CLDFB_NO_CHANNELS_MAX ); + + pAE->use_er = roomAcousticsConfig.use_er; + + if ( pAE->use_er == 1 ) + { + pAE->lowComplexity = roomAcousticsConfig.lowComplexity; + pAE->dimensions.x = roomAcousticsConfig.dimensions.x; + pAE->dimensions.y = roomAcousticsConfig.dimensions.y; + pAE->dimensions.z = roomAcousticsConfig.dimensions.z; + pAE->ListenerOrigin.x = roomAcousticsConfig.ListenerOrigin.x; + pAE->ListenerOrigin.y = roomAcousticsConfig.ListenerOrigin.y; + pAE->ListenerOrigin.z = roomAcousticsConfig.ListenerOrigin.z; + + mvr2r( roomAcousticsConfig.AbsCoeff, pAE->AbsCoeff, IVAS_ROOM_ABS_COEFF ); + } + + return IVAS_ERR_OK; +} + + +/*---------------------------------------------------------------------* + * IVAS_DEC_GetAcousticEnvironment( ) + * + * Gets acoustic environment configuration with a given ID + *---------------------------------------------------------------------*/ + +ivas_error IVAS_DEC_GetAcousticEnvironment( + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + uint16_t aeID, /* i : Acoustic environment ID */ + IVAS_ROOM_ACOUSTICS_CONFIG_DATA *pAcEnv /* o : Room acoustic environment data pointer */ +) +{ + uint16_t n, m; + uint16_t found = 0; + Decoder_Struct *st_ivas; + + if ( hIvasDec == NULL || pAcEnv == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + st_ivas = hIvasDec->st_ivas; + + /* In case of default AE ID, select the first one available */ + if ( aeID == IVAS_DEFAULT_AEID && st_ivas->acousticEnvironmentsCount > 0 ) + { + aeID = st_ivas->pAcousticEnvironments[0].aeID; + } + + for ( n = 0; n < st_ivas->acousticEnvironmentsCount; n++ ) + { + IVAS_ROOM_ACOUSTICS_CONFIG_DATA ae = st_ivas->pAcousticEnvironments[n]; + + if ( aeID == ae.aeID ) + { + found = 1; + pAcEnv->aeID = aeID; + pAcEnv->nBands = ae.nBands; + pAcEnv->inputPreDelay = ae.inputPreDelay; + for ( m = 0; m < pAcEnv->nBands; m++ ) + { + pAcEnv->pFc_input[m] = ae.pFc_input[m]; + pAcEnv->pAcoustic_rt60[m] = ae.pAcoustic_rt60[m]; + pAcEnv->pAcoustic_dsr[m] = ae.pAcoustic_dsr[m]; + } + + /* If ER are allocated then propagate parameters */ + pAcEnv->use_er = ae.use_er; + if ( ae.use_er != 0 ) + { + pAcEnv->lowComplexity = ae.lowComplexity; + + pAcEnv->dimensions.x = ae.dimensions.x; + pAcEnv->dimensions.y = ae.dimensions.y; + pAcEnv->dimensions.z = ae.dimensions.z; + + pAcEnv->ListenerOrigin.x = ae.ListenerOrigin.x; + pAcEnv->ListenerOrigin.y = ae.ListenerOrigin.y; + pAcEnv->ListenerOrigin.z = ae.ListenerOrigin.z; + + for ( m = 0; m < IVAS_ROOM_ABS_COEFF; m++ ) + { + pAcEnv->AbsCoeff[m] = ae.AbsCoeff[m]; + } + } + } + } + + return found ? IVAS_ERR_OK : IVAS_ERR_ACOUSTIC_ENVIRONMENT_MISSING; +} +#endif + + /*---------------------------------------------------------------------* * copyRendererConfigStruct( ) * @@ -3205,6 +3527,9 @@ static ivas_error copyRendererConfigStruct( hRCout->renderer_type_override = IVAS_RENDER_TYPE_OVERRIDE_NONE; break; } +#endif +#ifdef IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT + hRCout->roomAcoustics.aeID = hRCin->roomAcoustics.aeID; #endif hRCout->roomAcoustics.nBands = hRCin->roomAcoustics.nBands; hRCout->roomAcoustics.acousticPreDelay = hRCin->roomAcoustics.acousticPreDelay; @@ -3302,6 +3627,9 @@ ivas_error IVAS_DEC_FeedRenderConfig( { hRenderConfig->renderer_type_override = IVAS_RENDER_TYPE_OVERRIDE_CREND; } +#endif +#ifdef IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT + hRenderConfig->roomAcoustics.aeID = renderConfig.roomAcoustics.aeID; #endif hRenderConfig->roomAcoustics.nBands = renderConfig.roomAcoustics.nBands; hRenderConfig->roomAcoustics.acousticPreDelay = renderConfig.roomAcoustics.acousticPreDelay; @@ -3389,6 +3717,136 @@ ivas_error IVAS_DEC_FeedRenderConfig( } +#ifdef IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT +/*---------------------------------------------------------------------* + * feedAcousticEnvPI( ) + * + * Set acoustic environment from the PI data + *---------------------------------------------------------------------*/ + +static ivas_error feedAcousticEnvPI( + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + const IVAS_PIDATA_ACOUSTIC_ENV hAcoustEnvPI /* i : Render configuration struct */ +) +{ + RENDER_CONFIG_HANDLE hRenderConfig; + Decoder_Struct *st_ivas; + ivas_error error; + + if ( hIvasDec == NULL || hIvasDec->st_ivas == NULL || hIvasDec->st_ivas->hRenderConfig == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + hRenderConfig = hIvasDec->st_ivas->hRenderConfig; + st_ivas = hIvasDec->st_ivas; + +#ifdef DEBUGGING + hRenderConfig->renderer_type_override = IVAS_RENDER_TYPE_OVERRIDE_NONE; + if ( renderConfig.renderer_type_override == IVAS_RENDER_TYPE_OVERRIDE_FASTCONV ) + { + hRenderConfig->renderer_type_override = IVAS_RENDER_TYPE_OVERRIDE_FASTCONV; + } + if ( renderConfig.renderer_type_override == IVAS_RENDER_TYPE_OVERRIDE_CREND ) + { + hRenderConfig->renderer_type_override = IVAS_RENDER_TYPE_OVERRIDE_CREND; + } +#endif + /* Ignore if AE ID already in use */ + if ( hRenderConfig->roomAcoustics.aeID == hAcoustEnvPI.aeid ) + { + return IVAS_ERR_OK; + } + + /* Attempt to load the one already available */ + if ( ( error = IVAS_DEC_GetAcousticEnvironment( hIvasDec, hAcoustEnvPI.aeid, &hRenderConfig->roomAcoustics ) ) == IVAS_ERR_ACOUSTIC_ENVIRONMENT_MISSING ) + { + /* Add the new compact room environment */ + IVAS_ROOM_ACOUSTICS_CONFIG_DATA acEnv; + + acEnv.aeID = hAcoustEnvPI.aeid; + acEnv.nBands = IVAS_PI_AE_NUM_BANDS; + acEnv.pFc_input[IVAS_PI_AE_LOW] = IVAS_PI_AE_LOW_FREQ; + acEnv.pFc_input[IVAS_PI_AE_MID] = IVAS_PI_AE_MID_FREQ; + acEnv.pFc_input[IVAS_PI_AE_HIGH] = IVAS_PI_AE_HIGH_FREQ; + acEnv.pAcoustic_rt60[IVAS_PI_AE_LOW] = hAcoustEnvPI.rt60[IVAS_PI_AE_LOW]; + acEnv.pAcoustic_rt60[IVAS_PI_AE_MID] = hAcoustEnvPI.rt60[IVAS_PI_AE_MID]; + acEnv.pAcoustic_rt60[IVAS_PI_AE_HIGH] = hAcoustEnvPI.rt60[IVAS_PI_AE_HIGH]; + acEnv.inputPreDelay = (float) ( 0.1 * hRenderConfig->roomAcoustics.pAcoustic_rt60[IVAS_PI_AE_MID] ); + acEnv.pAcoustic_dsr[IVAS_PI_AE_LOW] = powf( 10.0f, hAcoustEnvPI.dsr[IVAS_PI_AE_LOW] / 10.0f ); + acEnv.pAcoustic_dsr[IVAS_PI_AE_MID] = powf( 10.0f, hAcoustEnvPI.dsr[IVAS_PI_AE_MID] / 10.0f ); + acEnv.pAcoustic_dsr[IVAS_PI_AE_HIGH] = powf( 10.0f, hAcoustEnvPI.dsr[IVAS_PI_AE_HIGH] / 10.0f ); + + acEnv.use_er = hAcoustEnvPI.availEarlyReflections; + + if ( hAcoustEnvPI.availEarlyReflections ) + { + hRenderConfig->roomAcoustics.dimensions.x = hAcoustEnvPI.roomDimensions.x; + hRenderConfig->roomAcoustics.dimensions.y = hAcoustEnvPI.roomDimensions.y; + hRenderConfig->roomAcoustics.dimensions.z = hAcoustEnvPI.roomDimensions.z; + mvr2r( hAcoustEnvPI.absorbCoeffs, hRenderConfig->roomAcoustics.AbsCoeff, IVAS_ROOM_ABS_COEFF ); + } + + if ( ( error = IVAS_DEC_AddAcousticEnvironment( hIvasDec, acEnv ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( ( error = IVAS_DEC_GetAcousticEnvironment( hIvasDec, hAcoustEnvPI.aeid, &hRenderConfig->roomAcoustics ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + /* Re-initialize reverb instance if already available */ + + /* TD renderer Jot reverberator */ + if ( st_ivas->hReverb != NULL ) + { + if ( ( error = ivas_reverb_open( &st_ivas->hReverb, st_ivas->hHrtfStatistics, hRenderConfig, st_ivas->hDecoderConfig->output_Fs ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + /* CREND Jot reverberator */ + if ( st_ivas->hCrendWrapper != NULL && st_ivas->hCrendWrapper->hCrend[0] != NULL && st_ivas->hCrendWrapper->hCrend[0]->hReverb != NULL ) + { + if ( ( error = ivas_reverb_open( &st_ivas->hCrendWrapper->hCrend[0]->hReverb, st_ivas->hHrtfStatistics, hRenderConfig, st_ivas->hDecoderConfig->output_Fs ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + /* Parametric renderer reverberator */ + if ( st_ivas->hDiracDecBin[0] != NULL && st_ivas->hDiracDecBin[0]->hReverb != NULL ) + { + ivas_binaural_reverb_close( &( st_ivas->hDiracDecBin[0]->hReverb ) ); + + if ( ( error = ivas_binaural_reverb_init( &( st_ivas->hDiracDecBin[0]->hReverb ), st_ivas->hHrtfStatistics, st_ivas->hSpatParamRendCom->num_freq_bands, CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES, + &( hRenderConfig->roomAcoustics ), st_ivas->hDecoderConfig->output_Fs, NULL, NULL, NULL ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + /* FastConv renderer reverberator */ + if ( st_ivas->hBinRenderer != NULL && st_ivas->hBinRenderer->hReverb != NULL ) + { + ivas_binaural_reverb_close( &( st_ivas->hBinRenderer->hReverb ) ); + + if ( ( error = ivas_binaural_reverb_init( &( st_ivas->hBinRenderer->hReverb ), st_ivas->hHrtfStatistics, st_ivas->hBinRenderer->conv_band, st_ivas->hBinRenderer->timeSlots, + &( hRenderConfig->roomAcoustics ), st_ivas->hDecoderConfig->output_Fs, NULL, NULL, NULL ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + return IVAS_ERR_OK; +} + +#endif + /*---------------------------------------------------------------------* * IVAS_DEC_GetDelay( ) * @@ -4204,15 +4662,41 @@ ivas_error IVAS_DEC_Flush( } +#ifdef DECODER_FORMAT_SWITCHING /*---------------------------------------------------------------------* - * IVAS_DEC_VoIP_IsEmpty( ) + * IVAS_DEC_isRestartNeeded( ) * * *---------------------------------------------------------------------*/ -bool IVAS_DEC_VoIP_IsEmpty( - IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ - const int16_t nSamplesAsked /* i : number of output samples asked */ +ivas_error IVAS_DEC_isRestartNeeded( + IVAS_DEC_HANDLE hIvasDec, /* i : IVAS decoder handle */ + bool *restartNeeded /* o : flag to signal decoder restart */ + +) +{ + if ( hIvasDec == NULL || hIvasDec->st_ivas == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + *restartNeeded = hIvasDec->st_ivas->restartNeeded > 0; + + return IVAS_ERR_OK; +} + + +#endif +/*---------------------------------------------------------------------* + * IVAS_DEC_VoIP_IsEmpty( ) + * + * Returns 'true' if decoder has no data in VoIP jitter buffer + *---------------------------------------------------------------------*/ + +ivas_error IVAS_DEC_VoIP_IsEmpty( + IVAS_DEC_HANDLE hIvasDec, /* i : IVAS decoder handle */ + const int16_t nSamplesAsked, /* i : number of output samples asked */ + bool *isEmpty /* o : isEmpty flag */ ) { if ( hIvasDec == NULL || hIvasDec->hVoIP == NULL ) @@ -4220,7 +4704,9 @@ bool IVAS_DEC_VoIP_IsEmpty( return IVAS_ERR_UNEXPECTED_NULL_POINTER; } - return ( ( JB4_bufferedDataUnits( hIvasDec->hVoIP->hJBM ) == 0 ) && ( hIvasDec->nSamplesAvailableNext < nSamplesAsked ) ); + *isEmpty = ( JB4_bufferedDataUnits( hIvasDec->hVoIP->hJBM ) == 0 ) && ( hIvasDec->nSamplesAvailableNext < nSamplesAsked ); + + return IVAS_ERR_OK; } @@ -4418,7 +4904,20 @@ static ivas_error printConfigInfo_dec( } else { - fprintf( stdout, "Output configuration: mono EVS bit-exact decoding\n" ); +#ifdef FIX_1419_MONO_STEREO_UMX + output_config = st_ivas->hDecoderConfig->output_config; + if ( output_config != IVAS_AUDIO_CONFIG_MONO ) + { + get_channel_config( output_config, &config_str[0] ); + fprintf( stdout, "Output configuration: mono EVS bit-exact decoding rendering to %s\n", config_str ); + } + else + { +#endif + fprintf( stdout, "Output configuration: mono EVS bit-exact decoding\n" ); +#ifdef FIX_1419_MONO_STEREO_UMX + } +#endif } } else @@ -4665,7 +5164,11 @@ static ivas_error evs_dec_main( { DEC_CORE_HANDLE *hCoreCoder; float mixer_left, mixer_rigth; +#ifdef FIX_1419_MONO_STEREO_UMX /* required now that mono can render to a higher number of output channels */ + float *p_output[MAX_TRANSPORT_CHANNELS]; +#else float *p_output[MAX_OUTPUT_CHANNELS_IN_DIEGETIC_PAN]; +#endif int16_t ch, nOutSamples; ivas_error error; @@ -4675,9 +5178,19 @@ static ivas_error evs_dec_main( mdct_switching_dec( hCoreCoder[0] ); +#ifdef FIX_1419_MONO_STEREO_UMX + for ( ch = 0; ch < MAX_TRANSPORT_CHANNELS; ch++ ) +#else for ( ch = 0; ch < MAX_OUTPUT_CHANNELS_IN_DIEGETIC_PAN; ch++ ) +#endif { p_output[ch] = st_ivas->p_output_f[ch]; +#ifdef FIX_1419_MONO_STEREO_UMX + if ( p_output[ch] != NULL ) + { + set_zero( p_output[ch], L_FRAME48k ); + } +#endif } /* run the main EVS decoding routine */ @@ -4733,7 +5246,11 @@ static ivas_error evs_dec_main( v_multc( p_output[0], mixer_left, p_output[0], nOutSamples ); } +#ifdef FIX_1419_MONO_STEREO_UMX + if ( st_ivas->hDecoderConfig->Opt_tsm && st_ivas->hDecoderConfig->nchan_out == 1 ) +#else if ( st_ivas->hDecoderConfig->Opt_tsm ) +#endif { /* BE workaround: in order to keep EVS bit-exact wrt. TS 26.443, convert 'float' output data to 'short' before the TSM */ int16_t pcm_buf_local[L_FRAME48k]; @@ -5538,86 +6055,119 @@ ivas_error IVAS_DEC_is_split_rendering_coded_out( return IVAS_ERR_OK; } + /*---------------------------------------------------------------------* - * IVAS_DEC_feedSinglePIorientation( ) + * feedSinglePIorientation( ) * * Feed a single orientation PI data to external orientation handle. *---------------------------------------------------------------------*/ -static ivas_error IVAS_DEC_feedSinglePIorientation( - IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ - bool isOrientationSaved, /* i : flag to indicate if an orientation for this PI type was previously saved */ - IVAS_QUATERNION *savedOrientation /* i : previously saved orientation for this PI type */ +static ivas_error feedSinglePIorientation( + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + IVAS_QUATERNION *orientation /* i : orientation for this PI type */ ) { int16_t i; - ivas_error error = IVAS_ERR_OK; - IVAS_QUATERNION savedInvOrientation; + ivas_error error; + Decoder_Struct *st_ivas; + IVAS_QUATERNION invOrientation; + + if ( hIvasDec == NULL || hIvasDec->st_ivas == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + st_ivas = hIvasDec->st_ivas; - if ( isOrientationSaved ) + if ( !st_ivas->hExtOrientationData ) { - if ( !hIvasDec->st_ivas->hExtOrientationData ) + if ( ( error = ivas_external_orientation_open( &( st_ivas->hExtOrientationData ), st_ivas->hDecoderConfig->render_framesize ) ) != IVAS_ERR_OK ) { - if ( ( error = ivas_external_orientation_open( &( hIvasDec->st_ivas->hExtOrientationData ), hIvasDec->st_ivas->hDecoderConfig->render_framesize ) ) != IVAS_ERR_OK ) - { - return error; - } + return error; } + } - if ( !hIvasDec->st_ivas->hCombinedOrientationData ) + if ( !st_ivas->hCombinedOrientationData ) + { + if ( ( error = ivas_combined_orientation_open( &( st_ivas->hCombinedOrientationData ), st_ivas->hDecoderConfig->output_Fs, st_ivas->hDecoderConfig->render_framesize ) ) != IVAS_ERR_OK ) { - if ( ( error = ivas_combined_orientation_open( &( hIvasDec->st_ivas->hCombinedOrientationData ), hIvasDec->st_ivas->hDecoderConfig->output_Fs, hIvasDec->st_ivas->hDecoderConfig->render_framesize ) ) != IVAS_ERR_OK ) - { - return error; - } + return error; } + } - QuaternionInverse( *savedOrientation, &savedInvOrientation ); + QuaternionInverse( *orientation, &invOrientation ); - /* use the new PI orientation or the previously saved orientation in processing */ - for ( i = 0; i < hIvasDec->st_ivas->hExtOrientationData->num_subframes; i++ ) - { - QuaternionProduct( hIvasDec->st_ivas->hExtOrientationData->Quaternions[i], savedInvOrientation, - &hIvasDec->st_ivas->hExtOrientationData->Quaternions[i] ); - hIvasDec->st_ivas->hExtOrientationData->enableExternalOrientation[i] = true; - } - hIvasDec->updateOrientation = true; + /* use the new PI orientation or the previously saved orientation in processing */ + for ( i = 0; i < st_ivas->hExtOrientationData->num_subframes; i++ ) + { + QuaternionProduct( st_ivas->hExtOrientationData->Quaternions[i], invOrientation, + &st_ivas->hExtOrientationData->Quaternions[i] ); + st_ivas->hExtOrientationData->enableExternalOrientation[i] = true; } - return error; + + hIvasDec->updateOrientation = true; + + return IVAS_ERR_OK; } #ifdef RTP_S4_251135_CR26253_0016_REV1 /*---------------------------------------------------------------------* - * IVAS_DEC_setDiegeticInput( ) + * setDiegeticInput( ) * * Set isDiegeticInput flag for combined orientation handle based on PI data. *---------------------------------------------------------------------*/ -static void IVAS_DEC_setDiegeticInputPI( - IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ - const bool *diegeticPIValues /* i : diegetic values for the input stream */ +static void setDiegeticInputPI( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ + const bool *diegeticPIValues /* i : diegetic values for the input stream */ ) { - if ( hIvasDec->st_ivas->hCombinedOrientationData != NULL ) + int16_t i; + + if ( st_ivas->hCombinedOrientationData != NULL ) { - int8_t i; for ( i = 0; i < ( 1 + IVAS_MAX_NUM_OBJECTS ); i++ ) { - hIvasDec->st_ivas->hCombinedOrientationData->isDiegeticInputPI[i] = diegeticPIValues[i]; + st_ivas->hCombinedOrientationData->isDiegeticInputPI[i] = diegeticPIValues[i]; } - hIvasDec->st_ivas->hCombinedOrientationData->isDiegeticInputPISet = true; + + st_ivas->hCombinedOrientationData->isDiegeticInputPISet = true; } + + return; } #endif + #ifdef IVAS_RTPDUMP -ivas_error IVAS_RTP_FeedPiDataToDecoder( IVAS_DEC_HANDLE hIvasDec, PIDATA_TS *piData, uint32_t numPiData ) +/*---------------------------------------------------------------------* + * IVAS_DEC_FeedPiDataToDecoder( ) + * + * + *---------------------------------------------------------------------*/ + +ivas_error IVAS_DEC_FeedPiDataToDecoder( + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + hPiDataTs piData, /* i : PI data received in rtp packet */ + uint32_t numPiData /* i : number of PI data received in rtp packet */ +) { + uint32_t i; + Decoder_Struct *st_ivas; ivas_error error = IVAS_ERR_OK; - while ( numPiData-- ) + + if ( hIvasDec == NULL || hIvasDec->st_ivas == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + st_ivas = hIvasDec->st_ivas; + + for ( i = 0; i < numPiData; i++ ) { uint32_t piDataType = piData->data.noPiData.piDataType; + switch ( piDataType ) { case IVAS_PI_SCENE_ORIENTATION: @@ -5626,7 +6176,7 @@ ivas_error IVAS_RTP_FeedPiDataToDecoder( IVAS_DEC_HANDLE hIvasDec, PIDATA_TS *pi #ifdef DEBUGGING fprintf( stdout, "PI_SCENE_ORIENTATION : %f, %f, %f, %f\n", quat->w, quat->x, quat->y, quat->z ); #endif - error = IVAS_DEC_feedSinglePIorientation( hIvasDec, true, quat ); + error = feedSinglePIorientation( hIvasDec, quat ); } break; @@ -5636,9 +6186,25 @@ ivas_error IVAS_RTP_FeedPiDataToDecoder( IVAS_DEC_HANDLE hIvasDec, PIDATA_TS *pi #ifdef DEBUGGING fprintf( stdout, "PI_DEVICE_ORIENTATION : %f, %f, %f, %f\n", quat->w, quat->x, quat->y, quat->z ); #endif - error = IVAS_DEC_feedSinglePIorientation( hIvasDec, true, quat ); + error = feedSinglePIorientation( hIvasDec, quat ); + } + break; + +#ifdef IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT + case IVAS_PI_ACOUSTIC_ENVIRONMENT: + { + uint16_t aeid = piData->data.acousticEnv.aeid; +#ifdef DEBUGGING + fprintf( stdout, "PI_ACOUSTIC_ENVIRONMENT : AEID : %d\n", aeid ); +#endif + + if ( piData->data.acousticEnv.availLateReverb && st_ivas->hRenderConfig != NULL && aeid != st_ivas->hRenderConfig->roomAcoustics.aeID ) + { + error = feedAcousticEnvPI( hIvasDec, piData->data.acousticEnv ); + } } break; +#endif #ifdef RTP_S4_251135_CR26253_0016_REV1 case IVAS_PI_DIEGETIC_TYPE: @@ -5646,7 +6212,7 @@ ivas_error IVAS_RTP_FeedPiDataToDecoder( IVAS_DEC_HANDLE hIvasDec, PIDATA_TS *pi #ifdef DEBUGGING fprintf( stdout, "PI_DIEGETIC_TYPE : %d, %d, %d, %d, %d\n", piData->data.digeticIndicator.isDiegetic[0], piData->data.digeticIndicator.isDiegetic[1], piData->data.digeticIndicator.isDiegetic[2], piData->data.digeticIndicator.isDiegetic[3], piData->data.digeticIndicator.isDiegetic[4] ); #endif - IVAS_DEC_setDiegeticInputPI( hIvasDec, piData->data.digeticIndicator.isDiegetic ); + setDiegeticInputPI( st_ivas, piData->data.digeticIndicator.isDiegetic ); } break; #endif @@ -5657,12 +6223,15 @@ ivas_error IVAS_RTP_FeedPiDataToDecoder( IVAS_DEC_HANDLE hIvasDec, PIDATA_TS *pi } break; } + if ( error != IVAS_ERR_OK ) { return error; } + piData++; } - return error; + + return IVAS_ERR_OK; } #endif diff --git a/lib_dec/lib_dec.h b/lib_dec/lib_dec.h index d0d2b501d847425d71c701665cda87ba15f71d36..24a663bd35c8d355d60cacedae8591d6bd275e66 100644 --- a/lib_dec/lib_dec.h +++ b/lib_dec/lib_dec.h @@ -71,7 +71,6 @@ typedef enum _IVAS_DEC_PCM_TYPE IVAS_DEC_PCM_INVALID } IVAS_DEC_PCM_TYPE; - /* bitstream formats that can be consumed */ typedef enum _IVAS_DEC_BS_FORMAT { @@ -87,6 +86,7 @@ typedef enum _IVAS_DEC_BS_FORMAT } IVAS_DEC_BS_FORMAT; typedef struct IVAS_DEC *IVAS_DEC_HANDLE; +typedef struct pidata_ts_struct *hPiDataTs; #ifdef SUPPORT_JBM_TRACEFILE /* Callback function for JBM tracefile writing */ @@ -119,6 +119,9 @@ ivas_error IVAS_DEC_Configure( const bool enableExternalOrientation, /* i : enable external orientations */ const IVAS_HEAD_ORIENT_TRK_T orientation_tracking, /* i : head orientation tracking type */ const bool renderConfigEnabled, /* i : enable Renderer config. file for binaural output */ +#ifdef FIX_1318_ROOM_SIZE_CMD_LINE + const IVAS_ROOM_SIZE_T roomSize, /* i : room size selector for reverb */ +#endif const bool non_diegetic_pan_enabled, /* i : enabled diegetic panning */ const float non_diegetic_pan_gain, /* i : non diegetic panning gain */ const bool dpidEnabled, /* i : enable directivity pattern option */ @@ -339,6 +342,13 @@ ivas_error IVAS_DEC_Flush( int16_t *nSamplesFlushed /* o : number of samples flushed */ ); +#ifdef DECODER_FORMAT_SWITCHING +ivas_error IVAS_DEC_isRestartNeeded( + IVAS_DEC_HANDLE hIvasDec, /* i : IVAS decoder handle */ + bool *restartNeeded /* o : flag to signal decoder restart */ +); + +#endif /* Setter functions - apply changes to decoder configuration */ /*! r: error code */ @@ -354,33 +364,33 @@ ivas_error IVAS_DEC_EnableSplitRendering( ); ivas_error IVAS_DEC_SetRenderFramesize( - IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ - const IVAS_RENDER_FRAMESIZE render_framesize /* i : render framesize */ + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + const IVAS_RENDER_FRAMESIZE render_framesize /* i : render framesize */ ); ivas_error IVAS_DEC_GetRenderFramesize( - IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ - IVAS_RENDER_FRAMESIZE *render_framesize /* o : render framesize */ + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + IVAS_RENDER_FRAMESIZE *render_framesize /* o : render framesize */ ); ivas_error IVAS_DEC_GetRenderFramesizeSamples( - IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ - int16_t *render_framesize /* o : render framesize in samples */ + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + int16_t *render_framesize /* o : render framesize in samples */ ); ivas_error IVAS_DEC_GetReferencesUpdateFrequency( - IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ - int16_t *update_frequency /* o : update frequency */ + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + int16_t *update_frequency /* o : update frequency */ ); ivas_error IVAS_DEC_GetNumOrientationSubframes( - IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ - int16_t *num_subframes /* o : render framesize */ + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + int16_t *num_subframes /* o : render framesize */ ); ivas_error IVAS_DEC_GetRenderFramesizeMs( - IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ - uint32_t *render_framesize /* o : render framesize in samples */ + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + uint32_t *render_framesize /* o : render framesize in samples */ ); #ifdef DEBUGGING @@ -475,6 +485,19 @@ ivas_error IVAS_DEC_HRTF_binary_close( const IVAS_BIN_RENDERER_TYPE binaural_renderer_old /* i : previous binaural renderer type */ ); +#ifdef IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT +ivas_error IVAS_DEC_AddAcousticEnvironment( + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + const IVAS_ROOM_ACOUSTICS_CONFIG_DATA roomAcousticsConfig /* i : Room acoustic configuration */ +); + +ivas_error IVAS_DEC_GetAcousticEnvironment( + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + uint16_t aeID, /* i : Acoustic environment ID */ + IVAS_ROOM_ACOUSTICS_CONFIG_DATA *pAcEnv /* o : Room acoustic environment data pointer */ +); +#endif + /*! r: error code*/ ivas_error IVAS_DEC_GetRenderConfig( IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ @@ -505,10 +528,11 @@ ivas_error IVAS_DEC_HasDecodedFirstGoodFrame( bool *hasDecodedFirstGoodFrame /* o : flag indicating if the decoder has decoded a good frame since it was configured */ ); -/*! r: true if decoder has no data in VoIP jitter buffer */ -bool IVAS_DEC_VoIP_IsEmpty( - IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ - const int16_t nSamplesAsked +/*! r: error code */ +ivas_error IVAS_DEC_VoIP_IsEmpty( + IVAS_DEC_HANDLE hIvasDec, /* i : IVAS decoder handle */ + const int16_t nSamplesAsked, /* i : number of output samples asked */ + bool *isEmpty /* o : isEmpty flag */ ); ivas_error IVAS_DEC_VoIP_Get_CA_offset( @@ -524,6 +548,15 @@ ivas_error IVAS_DEC_GetJbmData( ); #endif +#ifdef IVAS_RTPDUMP +ivas_error IVAS_DEC_FeedPiDataToDecoder( + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + hPiDataTs piData, /* i : PI data received in rtp packet */ + uint32_t numPiData /* i : number of PI data received in rtp packet */ +); +#endif + + /* Utility functions */ /*! r: pointer to an error message string */ @@ -557,11 +590,6 @@ void IVAS_DEC_PrintDisclaimer( void ); -#ifdef IVAS_RTPDUMP -#include "ivas_rtp_pi_data.h" -ivas_error IVAS_RTP_FeedPiDataToDecoder( IVAS_DEC_HANDLE hIvasDec, PIDATA_TS *piData, uint32_t numPiData ); -#endif - /* clang-format on */ #endif diff --git a/lib_enc/ivas_spar_encoder.c b/lib_enc/ivas_spar_encoder.c index 79b00113fcc57bcd55e3951aac232820daa1e3bf..0cb0cf6e60517e3e6c89b1245607ed4de4472d42 100644 --- a/lib_enc/ivas_spar_encoder.c +++ b/lib_enc/ivas_spar_encoder.c @@ -838,7 +838,11 @@ static ivas_error ivas_spar_enc_process( { /*cross fade between new active W channels and old passive W channel*/ +#ifdef BE_FIX_1391_COVERAGE_SPAR_DYN__CHANNEL + if ( dyn_active_w_flag == 1 || hSpar->hMdEnc->spar_md.prior_dyn_active_w_flag == 1 ) +#else if ( dyn_active_w_flag == 1 ) +#endif { if ( hSpar->hMdEnc->spar_md.prior_dyn_active_w_flag != dyn_active_w_flag ) { diff --git a/lib_enc/ivas_stat_enc.h b/lib_enc/ivas_stat_enc.h index 2620fb3e976a67c8a2649eb75eee07cd0b51d03d..1dcf4f2536274ccc1fe5d1ce530defd8945ff7b4 100644 --- a/lib_enc/ivas_stat_enc.h +++ b/lib_enc/ivas_stat_enc.h @@ -1081,6 +1081,12 @@ typedef struct stereo_dmx_evs_correlation_filter_structure { float isd_rate_s; float iccr_s; +#ifdef FIX_1430_EVS_STEREO_DMX_CHANNEL_DISAPPEARING + float phitd; + float iccres_s; + float lvlin[CPE_CHANNELS]; +#endif + float ipd_ff[STEREO_DMX_EVS_NB_SUBBAND_MAX]; float Pr[STEREO_DMX_EVS_NB_SUBBAND_MAX]; float Pi[STEREO_DMX_EVS_NB_SUBBAND_MAX]; diff --git a/lib_enc/ivas_stereo_dmx_evs.c b/lib_enc/ivas_stereo_dmx_evs.c index bf516cb97439c21daef70b57c2be26dcbd254cd5..e25ce350a448acf152db46df4f6c8eadd6741768 100644 --- a/lib_enc/ivas_stereo_dmx_evs.c +++ b/lib_enc/ivas_stereo_dmx_evs.c @@ -78,6 +78,15 @@ #define STEREO_DMX_EVS_ICCR_HYST_L 0.75f #define STEREO_DMX_EVS_ICCR_HYST_H 0.85f +#ifdef FIX_1430_EVS_STEREO_DMX_CHANNEL_DISAPPEARING +#define STEREO_DMX_EVS_ICCRES_FORGETTING 0.92f +#define STEREO_DMX_EVS_LVLU_FORGETTING 0.5f +#define STEREO_DMX_EVS_LVLD_FORGETTING 0.92f +#define STEREO_DMX_EVS_ICLD_THRESH 3.f +#define STEREO_DMX_EVS_ICCRES_THRESH 0.4f +#define STEREO_DMX_EVS_DICLD_THRESH 1.49623566f +#endif + #define STEREO_DMX_EVS_SWTCH_HYS_THRES 1 #define STEREO_DMX_EVS_LR_EGY 15.0f #define STEREO_DMX_EVS_ILDS_EGY 10000.0f @@ -124,10 +133,15 @@ static void calc_poc( STEREO_DMX_EVS_POC_HANDLE hPOC, STEREO_DMX_EVS_PHA_HANDLE static ivas_error estimate_itd( float *corr, STEREO_DMX_EVS_POC_HANDLE hPOC, STEREO_DMX_EVS_PHA_HANDLE hPHA, const float srcL[], const float srcR[], float itd[], const int16_t input_frame ); static void weighted_ave( const float src1[], const float src2[], float dst[], const float gain, const float old_gain, const int16_t input_frame, const float wnd[] ); static void adapt_gain( const float src[], float dst[], const float gain, const float old_gain, const int16_t input_frame, const float wnd[] ); -static void create_M_signal( const float srcL[], const float srcR[], float dmx[], const float w_curr, const int16_t input_frame, const float wnd[], float *w_prev, float *dmx_energy, float *src_energy ); static float find_poc_peak( STEREO_DMX_EVS_POC_HANDLE hPOC, float itd[], const int16_t input_frame, const float ratio ); -static void calc_energy( const float src1[], const float src2[], float energy[], const int16_t input_frame, const float ratio ); static float spectral_flatness( const float sig[], const int16_t sig_length ); +#ifdef FIX_1430_EVS_STEREO_DMX_CHANNEL_DISAPPEARING +static void create_M_signal( const float srcL[], const float srcR[], float dmx[], const float w_curr, const int16_t input_frame, const float wnd[], float *w_prev, float *dmx_energy, float *src_energy, STEREO_DMX_EVS_PHA_HANDLE hPHA ); +static void calc_energy( const float src1[], const float src2[], float energy[], float *lvl, const int16_t input_frame, const float ratio ); +#else +static void create_M_signal( const float srcL[], const float srcR[], float dmx[], const float w_curr, const int16_t input_frame, const float wnd[], float *w_prev, float *dmx_energy, float *src_energy ); +static void calc_energy( const float src1[], const float src2[], float energy[], const int16_t input_frame, const float ratio ); +#endif /*-------------------------------------------------------------------* * estimate_itd_wnd_fft() @@ -485,7 +499,11 @@ static void calc_poc( Ni = 0; eneL = 0; eneR = 0; - +#ifdef FIX_1430_EVS_STEREO_DMX_CHANNEL_DISAPPEARING + step = n0 >> 3; + tmp1 = 0.0f; + tmp2 = 0.0f; +#endif for ( n = 1, i = 1; n < nsbd; n++ ) { tPr = 0.0f; @@ -518,13 +536,20 @@ static void calc_poc( eneL += ( specLr[i] * specLr[i] + specLi[i] * specLi[i] ); eneR += ( specRr[i] * specRr[i] + specRi[i] * specRi[i] ); + +#ifdef FIX_1430_EVS_STEREO_DMX_CHANNEL_DISAPPEARING + if ( i == step - 1 ) + { + tmp1 = eneL; + tmp2 = eneR; + } +#endif } Pn = inv_sqrtf( ( tPr * tPr + tPi * tPi ) + EPSILON ); tPr *= Pn; tPi *= Pn; - Pr[n] = ipd_ff[n] * Pr[n] + ( 1.0f - ipd_ff[n] ) * tPr; Pi[n] = ipd_ff[n] * Pi[n] + ( 1.0f - ipd_ff[n] ) * tPi; Pn = inv_sqrtf( ( Pr[n] * Pr[n] + Pi[n] * Pi[n] ) + EPSILON ); @@ -536,8 +561,12 @@ static void calc_poc( } /* Computes Spectral flatness on one channel */ +#ifdef FIX_1430_EVS_STEREO_DMX_CHANNEL_DISAPPEARING + if ( spectral_flatness( &tEl[1], nsbd - 1 ) < hPHA->pha_ipd_sf_Threshold ) +#else tmp1 = spectral_flatness( &tEl[1], nsbd - 1 ); if ( tmp1 < hPHA->pha_ipd_sf_Threshold ) +#endif { hPHA->pha_ipd_chanswitch_allowed = 0; } @@ -549,6 +578,34 @@ static void calc_poc( ICCr = sqrtf( ( Nr * Nr + Ni * Ni ) / ( eneL * eneR + EPSILON ) ); hPHA->iccr_s = STEREO_DMX_EVS_ICCR_FORGETTING * hPHA->iccr_s + ( 1.0f - STEREO_DMX_EVS_ICCR_FORGETTING ) * ICCr; +#ifdef FIX_1430_EVS_STEREO_DMX_CHANNEL_DISAPPEARING + eneL -= tmp1; + eneR -= tmp2; + + IPDr = cosf( hPHA->phitd * step ); + IPDi = sinf( hPHA->phitd * step ); + tmp1 = cosf( hPHA->phitd ); + tmp2 = sinf( hPHA->phitd ); + + for ( Nr = 0, Ni = 0, i = step; i < ( n0 - 1 ); i++ ) + { + tIPDr = ( specRr[i] * IPDr + specRi[i] * IPDi ); + tIPDi = ( specRr[i] * IPDi - specRi[i] * IPDr ); + Nr += ( specLr[i] * tIPDr - specLi[i] * tIPDi ); + Ni += ( specLi[i] * tIPDr + specLr[i] * tIPDi ); + tIPDr = IPDr; + IPDr = tIPDr * tmp1 - IPDi * tmp2; + IPDi = tIPDr * tmp2 + IPDi * tmp1; + } + + if ( ICCr == 0.f ) + { + ICCr = 1; + } + ICCr = 0.5f * ( ICCr + ( sqrtf( ( Nr * Nr + Ni * Ni ) / ( eneL * eneR + EPSILON ) ) ) ); + hPHA->iccres_s = STEREO_DMX_EVS_ICCRES_FORGETTING * hPHA->iccres_s + ( 1.0f - STEREO_DMX_EVS_ICCRES_FORGETTING ) * ICCr; +#endif + if ( hPHA->curr_pha == STEREO_DMX_EVS_PHA_IPD ) { hPHA->force_poc = FALSE; @@ -1142,7 +1199,16 @@ static float spectral_flatness( * * calculate energy *-------------------------------------------------------------------*/ - +#ifdef FIX_1430_EVS_STEREO_DMX_CHANNEL_DISAPPEARING +static void calc_energy( + const float src1[], /* i : Lch input signal */ + const float src2[], /* i : Rch input signal */ + float energy[], /* o : calculated energy */ + float *lvl, /* o : calculated rms level */ + const int16_t input_frame, /* i : input frame length per channel */ + const float ratio /* i : adapting ratio */ +) +#else static void calc_energy( const float src1[], /* i : Lch input signal */ const float src2[], /* i : Rch input signal */ @@ -1150,8 +1216,13 @@ static void calc_energy( const int16_t input_frame, /* i : input frame length per channel */ const float ratio /* i : adapting ratio */ ) +#endif { +#ifdef FIX_1430_EVS_STEREO_DMX_CHANNEL_DISAPPEARING + float E, wnd, wnd_diff, lvli, lvlff; +#else float E, wnd, wnd_diff; +#endif int16_t i, adaptlen; /* Initialization */ @@ -1179,6 +1250,14 @@ static void calc_energy( *energy = *energy * ratio + ( E / (float) input_frame ) * ( 1.0f - ratio ); +#ifdef FIX_1430_EVS_STEREO_DMX_CHANNEL_DISAPPEARING + if ( lvl != NULL ) + { + lvli = log10f( E + EPSILON ); + lvlff = ( lvli > *lvl ) ? STEREO_DMX_EVS_LVLU_FORGETTING : STEREO_DMX_EVS_LVLD_FORGETTING; + *lvl = lvlff * *lvl + ( 1.0f - lvlff ) * lvli; + } +#endif return; } @@ -1215,8 +1294,6 @@ static void adapt_gain( const float wnd[] /* i : window coef */ ) { - - int16_t i, len, len2; float gain_tmp, gain_sub; @@ -1235,13 +1312,11 @@ static void adapt_gain( dst[i] = src[i] * gain_tmp; } - for ( ; i < input_frame; i++ ) { dst[i] = src[i] * gain; } - return; } @@ -1251,7 +1326,20 @@ static void adapt_gain( * * create downmix signal *-------------------------------------------------------------------*/ - +#ifdef FIX_1430_EVS_STEREO_DMX_CHANNEL_DISAPPEARING +static void create_M_signal( + const float srcL[], /* i : Lch input signal */ + const float srcR[], /* i : Rch input signal */ + float dmx[], /* o : output signal */ + const float w_curr, /* i : adapting weight */ + const int16_t input_frame, /* i : input frame length per channel */ + const float wnd[], /* i : window coef */ + float *w_prev, /* i/o: adapting prev weight */ + float *dmx_energy, /* i/o: downmix signal energy */ + float *src_energy, /* i/o: input signal energy */ + STEREO_DMX_EVS_PHA_HANDLE hPHA /* i/o: correlation filter structure */ +) +#else static void create_M_signal( const float srcL[], /* i : Lch input signal */ const float srcR[], /* i : Rch input signal */ @@ -1263,6 +1351,7 @@ static void create_M_signal( float *dmx_energy, /* i/o: downmix signal energy */ float *src_energy /* i/o: input signal energy */ ) +#endif { float weighted[L_FRAME48k], eps, amp_mod[CPE_CHANNELS], Lbias; @@ -1272,9 +1361,15 @@ static void create_M_signal( weighted_ave( srcL, srcR, dmx, w_curr, w_prev[0], input_frame, wnd ); +#ifdef FIX_1430_EVS_STEREO_DMX_CHANNEL_DISAPPEARING + calc_energy( srcL, srcL, src_energy, hPHA->lvlin, input_frame, STEREO_DMX_EVS_DMX_EGY_FORGETTING ); + calc_energy( srcR, srcR, src_energy + 1, hPHA->lvlin + 1, input_frame, STEREO_DMX_EVS_DMX_EGY_FORGETTING ); + calc_energy( dmx, dmx, dmx_energy, NULL, input_frame, STEREO_DMX_EVS_DMX_EGY_FORGETTING ); +#else calc_energy( srcL, srcL, src_energy, input_frame, STEREO_DMX_EVS_DMX_EGY_FORGETTING ); calc_energy( srcR, srcR, src_energy + 1, input_frame, STEREO_DMX_EVS_DMX_EGY_FORGETTING ); calc_energy( dmx, dmx, dmx_energy, input_frame, STEREO_DMX_EVS_DMX_EGY_FORGETTING ); +#endif if ( src_energy[0] * Lbias > src_energy[1] ) { @@ -1363,7 +1458,12 @@ void stereo_dmx_evs_enc( float *p_data_mem, *p_prev_taps, *p_curr_taps, *p_data, *p_sub_frame; float ftmp, *fad_g, *p_dmx_data, *p_dmx_data_fo; bool is_transient; + +#ifdef FIX_1430_EVS_STEREO_DMX_CHANNEL_DISAPPEARING + STEREO_DMX_EVS_PRC prev_prc, req_prc; +#else STEREO_DMX_EVS_PRC prev_prc; +#endif STEREO_DMX_EVS_PHA_HANDLE hPHA; if ( is_binaural ) @@ -1423,8 +1523,14 @@ void stereo_dmx_evs_enc( dmx_weight = 0.5f; } +#ifdef FIX_1430_EVS_STEREO_DMX_CHANNEL_DISAPPEARING + hPHA->phitd = hStereoDmxEVS->itd * PI2 / input_frame; + create_M_signal( data_f[0], data_f[1], dmx_poc_data, dmx_weight, input_frame, hStereoDmxEVS->s_wnd, + hStereoDmxEVS->dmx_weight, hStereoDmxEVS->pre_dmx_energy, hStereoDmxEVS->aux_dmx_energy, hPHA ); +#else create_M_signal( data_f[0], data_f[1], dmx_poc_data, dmx_weight, input_frame, hStereoDmxEVS->s_wnd, hStereoDmxEVS->dmx_weight, hStereoDmxEVS->pre_dmx_energy, hStereoDmxEVS->aux_dmx_energy ); +#endif /* pha */ @@ -1494,6 +1600,38 @@ void stereo_dmx_evs_enc( prev_prc = hPHA->curr_prc; if ( abs( (int16_t) hStereoDmxEVS->itd ) > hPHA->prc_thres ) +#ifdef FIX_1430_EVS_STEREO_DMX_CHANNEL_DISAPPEARING + { + req_prc = STEREO_DMX_EVS_PRC_POC; + if ( ( fabs( hPHA->lvlin[0] - hPHA->lvlin[1] ) < STEREO_DMX_EVS_ICLD_THRESH ) && ( hPHA->iccres_s < STEREO_DMX_EVS_ICCRES_THRESH ) && ( ( ( dmx_weight + hStereoDmxEVS->dmx_weight[1] ) > STEREO_DMX_EVS_DICLD_THRESH * ( 1 - dmx_weight + hStereoDmxEVS->dmx_weight[2] ) ) || ( ( 1 - dmx_weight + hStereoDmxEVS->dmx_weight[2] ) > STEREO_DMX_EVS_DICLD_THRESH * ( dmx_weight + hStereoDmxEVS->dmx_weight[1] ) ) ) ) + { + req_prc = STEREO_DMX_EVS_PRC_PHA; + } + } + else + { + req_prc = STEREO_DMX_EVS_PRC_PHA; + } + + // Set mode with hysteresis + if ( hPHA->curr_prc != req_prc ) + { + if ( hPHA->prev_prc == req_prc ) + { + hPHA->prc_hys_cnt += 1; + } + else + { + hPHA->prc_hys_cnt = 0; + } + + if ( hPHA->prc_hys_cnt >= STEREO_DMX_EVS_SWTCH_PRC_HYS_THRES ) + { + hPHA->curr_prc = req_prc; + } + } + hPHA->prev_prc = req_prc; +#else { if ( hPHA->curr_prc != STEREO_DMX_EVS_PRC_POC ) { @@ -1533,6 +1671,7 @@ void stereo_dmx_evs_enc( } hPHA->prev_prc = STEREO_DMX_EVS_PRC_PHA; } +#endif if ( is_transient || ( hStereoDmxEVS->aux_dmx_energy[0] > STEREO_DMX_EVS_ILDS_EGY * hStereoDmxEVS->aux_dmx_energy[1] ) || ( hStereoDmxEVS->aux_dmx_energy[1] > STEREO_DMX_EVS_ILDS_EGY * hStereoDmxEVS->aux_dmx_energy[0] ) || ( hPHA->force_poc ) ) { @@ -1677,7 +1816,6 @@ void stereo_dmx_evs_enc( mvr2s( p_dmx_data, data, n_samples ); - return; } @@ -1837,6 +1975,14 @@ ivas_error stereo_dmx_evs_init_encoder( hStereoDmxEVS->hPHA->pha_len = len / 2; hStereoDmxEVS->hPHA->isd_rate_s = 0.0f; hStereoDmxEVS->hPHA->iccr_s = 0.0f; +#ifdef FIX_1430_EVS_STEREO_DMX_CHANNEL_DISAPPEARING + hStereoDmxEVS->hPHA->iccres_s = 0.0f; + hStereoDmxEVS->hPHA->phitd = 0.0f; + for ( n = 0; n < CPE_CHANNELS; n++ ) + { + hStereoDmxEVS->hPHA->lvlin[n] = 0.0f; + } +#endif pha_len = hStereoDmxEVS->hPHA->pha_len; fad_len = hStereoDmxEVS->hPHA->fad_len; diff --git a/lib_isar/isar_splitRendererPre.c b/lib_isar/isar_splitRendererPre.c index 370e02398d5a9cb2eae31418e531083b7490fd94..bd1c9c1b2dce6c0f1539825a77ca97a752667546 100644 --- a/lib_isar/isar_splitRendererPre.c +++ b/lib_isar/isar_splitRendererPre.c @@ -1894,6 +1894,9 @@ ivas_error splitRendLc3plusEncodeAndWrite( pBits->pose_correction = hSplitBin->multiBinPoseData.poseCorrectionMode; pBits->codec_frame_size_ms = (int16_t) ( hSplitBin->hLc3plusEnc->config.lc3plus_frame_duration_us / 1000 ); pBits->isar_frame_size_ms = (int16_t) ( hSplitBin->hLc3plusEnc->config.isar_frame_duration_us / 1000 ); +#ifdef FIX_1437_LC3PLUS_EXTREND_HIRES + pBits->lc3plus_highres = hSplitBin->hLc3plusEnc->config.high_res_mode_enabled; +#endif return IVAS_ERR_OK; } diff --git a/lib_rend/ivas_dirac_dec_binaural_functions.c b/lib_rend/ivas_dirac_dec_binaural_functions.c index 6a162142e88a00a1031a2e4d3b67b2a4e4a8ce67..ad63a5b2e9fef2556d44bc3f58ca2a4f37275503 100644 --- a/lib_rend/ivas_dirac_dec_binaural_functions.c +++ b/lib_rend/ivas_dirac_dec_binaural_functions.c @@ -2450,7 +2450,9 @@ static void getDirectPartGains( { float aziRad, eleRad; float y, mappedX, aziRadMapped, A, A2, A3; +#ifndef NONBE_FIX_1426_STEREO_PANNING_BETWEEN_OPT_LEVEL const float LsAngleRad = 30.0f * PI_OVER_180; +#endif if ( renderStereoOutputInsteadOfBinaural ) /* In stereo (i.e. non-binaural) rendering mode */ { @@ -2471,19 +2473,31 @@ static void getDirectPartGains( aziRadMapped = atan2f( y, mappedX ); /* Determine the real valued amplitude panning gains */ +#ifdef NONBE_FIX_1426_STEREO_PANNING_BETWEEN_OPT_LEVEL + if ( aziRadMapped >= LS_ANGLE_RAD_30_DEG ) +#else if ( aziRadMapped >= LsAngleRad ) +#endif { /* Left side */ *lRealp = 1.0f; *rRealp = 0.0f; } +#ifdef NONBE_FIX_1426_STEREO_PANNING_BETWEEN_OPT_LEVEL + else if ( aziRadMapped <= -LS_ANGLE_RAD_30_DEG ) +#else else if ( aziRadMapped <= -LsAngleRad ) +#endif { /* Right side */ *lRealp = 0.0f; *rRealp = 1.0f; } else /* Tangent panning law */ { +#ifdef NONBE_FIX_1426_STEREO_PANNING_BETWEEN_OPT_LEVEL + A = tanf( aziRadMapped ) * INV_TAN_LS_ANGLE_RAD_30_DEG; +#else A = tanf( aziRadMapped ) / tanf( LsAngleRad ); +#endif A2 = ( A - 1.0f ) / max( 0.001f, A + 1.0f ); A3 = 1.0f / ( A2 * A2 + 1.0f ); *lRealp = sqrtf( A3 ); @@ -3427,11 +3441,15 @@ static void ivas_masa_ext_rend_parambin_internal( ivas_dirac_dec_binaural_formulate_input_covariance_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, subframe, subFrameTotalEne, IIReneLimiter ); - +#ifdef NONBE_FIX_1442_MASA_EXT_REND_ORIENT_IDX + ivas_dirac_dec_binaural_formulate_target_covariance_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, Rmat, subframe, + hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[hCombinedOrientationData->subframe_idx] > 0, + subFrameTotalEne, IIReneLimiter, NULL ); +#else ivas_dirac_dec_binaural_formulate_target_covariance_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, Rmat, subframe, hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[subframe] > 0, subFrameTotalEne, IIReneLimiter, NULL ); - +#endif ivas_dirac_dec_binaural_determine_processing_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, max_band_decorr, Rmat, subframe, hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[hCombinedOrientationData->subframe_idx] > 0, 0, NULL ); @@ -3495,6 +3513,15 @@ static void ivas_masa_ext_rend_parambin_internal( mvr2r( hMasaExtRend->hDiracDecBin[0]->ChCrossRe, hDiracDecBin->ChCrossRe, hSpatParamRendCom->num_freq_bands ); mvr2r( hMasaExtRend->hDiracDecBin[0]->ChCrossIm, hDiracDecBin->ChCrossIm, hSpatParamRendCom->num_freq_bands ); +#ifdef NONBE_FIX_1442_MASA_EXT_REND_ORIENT_IDX + ivas_dirac_dec_binaural_formulate_target_covariance_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, Rmat_local, subframe, + hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[hCombinedOrientationData->subframe_idx] > 0, + subFrameTotalEne, IIReneLimiter, NULL ); + + ivas_dirac_dec_binaural_determine_processing_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, max_band_decorr, Rmat_local, subframe, + hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[hCombinedOrientationData->subframe_idx] > 0, + 0, NULL ); +#else ivas_dirac_dec_binaural_formulate_target_covariance_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, Rmat_local, subframe, hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[subframe] > 0, subFrameTotalEne, IIReneLimiter, NULL ); @@ -3502,7 +3529,7 @@ static void ivas_masa_ext_rend_parambin_internal( ivas_dirac_dec_binaural_determine_processing_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, max_band_decorr, Rmat_local, subframe, hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[subframe] > 0, 0, NULL ); - +#endif /* re-use reverb and decorr from main direction for the sides */ ivas_dirac_dec_binaural_process_output( hDiracDecBin, hSpatParamRendCom, hMasaExtRend->cldfbSynRend, output_f, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, diff --git a/lib_rend/ivas_prot_rend.h b/lib_rend/ivas_prot_rend.h index 112c6ac73ef0cecc89e9b23c51ff556ba8a60f6d..14c2e6594136a1480c09526a947409bbeea37b2e 100644 --- a/lib_rend/ivas_prot_rend.h +++ b/lib_rend/ivas_prot_rend.h @@ -735,9 +735,9 @@ ivas_error TDREND_MIX_SRC_SetDir( ); ivas_error TDREND_MIX_SRC_SetGain( - BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ - const int16_t SrcInd, /* i : Source index */ - const float Gain /* i : Gain */ + BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ + const int16_t SrcInd, /* i : Source index */ + const float Gain /* i : Gain */ ); ivas_error TDREND_MIX_SRC_SetDirAtten( @@ -1343,6 +1343,13 @@ ivas_error ivas_render_config_init_from_rom( RENDER_CONFIG_HANDLE *hRenderConfig /* i/o: Renderer config handle */ ); +#ifdef FIX_1318_ROOM_SIZE_CMD_LINE +ivas_error ivas_render_config_change_defaults( + RENDER_CONFIG_HANDLE hRenderConfig, /* i/o: Renderer config handle */ + IVAS_DefaultReverbSize reverbDefault /* i: Reverb default size */ +); + +#endif /*----------------------------------------------------------------------------------* * Quaternion operations diff --git a/lib_rend/ivas_render_config.c b/lib_rend/ivas_render_config.c index c3a39b426e39a0c1f372a5e0f88464c1c7e4c18b..dc44c003f2f5a3f1dd61d5c3952c62599e032cb8 100644 --- a/lib_rend/ivas_render_config.c +++ b/lib_rend/ivas_render_config.c @@ -45,8 +45,19 @@ * Local constants *-----------------------------------------------------------------------*/ +#ifdef FIX_1318_ROOM_SIZE_CMD_LINE +#define IVAS_REVERB_DEFAULT_L_PRE_DELAY 0.016f +#define IVAS_REVERB_DEFAULT_L_INPUT_DELAY 0.1f + +#define IVAS_REVERB_DEFAULT_S_PRE_DELAY 0.0125f +#define IVAS_REVERB_DEFAULT_S_INPUT_DELAY 0.0f + +#define IVAS_REVERB_DEFAULT_M_PRE_DELAY 0.0125f +#define IVAS_REVERB_DEFAULT_M_INPUT_DELAY 0.0f +#else #define IVAS_REVERB_DEFAULT_PRE_DELAY 0.016f #define IVAS_REVERB_DEFAULT_INPUT_DELAY 0.1f +#endif #define IVAS_REVERB_DEFAULT_USE_ER 0 @@ -113,17 +124,32 @@ ivas_error ivas_render_config_init_from_rom( #ifdef DEBUGGING ( *hRenderConfig )->renderer_type_override = IVAS_RENDER_TYPE_OVERRIDE_NONE; #endif +#ifdef IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT + ( *hRenderConfig )->roomAcoustics.aeID = IVAS_DEFAULT_AEID; +#endif +#ifdef FIX_1318_ROOM_SIZE_CMD_LINE + ( *hRenderConfig )->roomAcoustics.nBands = IVAS_REVERB_DEFAULT_L_N_BANDS; + ( *hRenderConfig )->roomAcoustics.acousticPreDelay = IVAS_REVERB_DEFAULT_L_PRE_DELAY; + ( *hRenderConfig )->roomAcoustics.inputPreDelay = IVAS_REVERB_DEFAULT_L_INPUT_DELAY; +#else ( *hRenderConfig )->roomAcoustics.nBands = IVAS_REVERB_DEFAULT_N_BANDS; ( *hRenderConfig )->roomAcoustics.acousticPreDelay = IVAS_REVERB_DEFAULT_PRE_DELAY; ( *hRenderConfig )->roomAcoustics.inputPreDelay = IVAS_REVERB_DEFAULT_INPUT_DELAY; +#endif ( *hRenderConfig )->roomAcoustics.use_er = IVAS_REVERB_DEFAULT_USE_ER; set_zero( &( *hRenderConfig )->roomAcoustics.pFc_input[0], CLDFB_NO_CHANNELS_MAX ); set_zero( &( *hRenderConfig )->roomAcoustics.pAcoustic_rt60[0], CLDFB_NO_CHANNELS_MAX ); set_zero( &( *hRenderConfig )->roomAcoustics.pAcoustic_dsr[0], CLDFB_NO_CHANNELS_MAX ); +#ifdef FIX_1318_ROOM_SIZE_CMD_LINE + mvr2r( ivas_reverb_default_large_fc, ( *hRenderConfig )->roomAcoustics.pFc_input, IVAS_REVERB_DEFAULT_L_N_BANDS ); + mvr2r( ivas_reverb_default_large_RT60, ( *hRenderConfig )->roomAcoustics.pAcoustic_rt60, IVAS_REVERB_DEFAULT_L_N_BANDS ); + mvr2r( ivas_reverb_default_large_DSR, ( *hRenderConfig )->roomAcoustics.pAcoustic_dsr, IVAS_REVERB_DEFAULT_L_N_BANDS ); +#else mvr2r( ivas_reverb_default_fc, ( *hRenderConfig )->roomAcoustics.pFc_input, IVAS_REVERB_DEFAULT_N_BANDS ); mvr2r( ivas_reverb_default_RT60, ( *hRenderConfig )->roomAcoustics.pAcoustic_rt60, IVAS_REVERB_DEFAULT_N_BANDS ); mvr2r( ivas_reverb_default_DSR, ( *hRenderConfig )->roomAcoustics.pAcoustic_dsr, IVAS_REVERB_DEFAULT_N_BANDS ); +#endif for ( i = 0; i < MAX_NUM_OBJECTS; i++ ) { @@ -150,3 +176,65 @@ ivas_error ivas_render_config_init_from_rom( return IVAS_ERR_OK; } + +#ifdef FIX_1318_ROOM_SIZE_CMD_LINE + +/*-------------------------------------------------------------------* + * ivas_render_config_change_defaults() + * + * Changes default values from ROM + *-------------------------------------------------------------------*/ + +ivas_error ivas_render_config_change_defaults( + RENDER_CONFIG_HANDLE hRenderConfig, /* i/o: Renderer config handle */ + IVAS_DefaultReverbSize defaultReverbSize /* i: Reverb default size */ +) +{ + switch ( defaultReverbSize ) + { + case DEFAULT_REVERB_SMALL: + hRenderConfig->roomAcoustics.nBands = IVAS_REVERB_DEFAULT_S_N_BANDS; + hRenderConfig->roomAcoustics.acousticPreDelay = IVAS_REVERB_DEFAULT_S_PRE_DELAY; + hRenderConfig->roomAcoustics.inputPreDelay = IVAS_REVERB_DEFAULT_S_INPUT_DELAY; + hRenderConfig->roomAcoustics.use_er = IVAS_REVERB_DEFAULT_USE_ER; + set_zero( &hRenderConfig->roomAcoustics.pFc_input[0], CLDFB_NO_CHANNELS_MAX ); + set_zero( &hRenderConfig->roomAcoustics.pAcoustic_rt60[0], CLDFB_NO_CHANNELS_MAX ); + set_zero( &hRenderConfig->roomAcoustics.pAcoustic_dsr[0], CLDFB_NO_CHANNELS_MAX ); + + mvr2r( ivas_reverb_default_small_fc, hRenderConfig->roomAcoustics.pFc_input, IVAS_REVERB_DEFAULT_S_N_BANDS ); + mvr2r( ivas_reverb_default_small_RT60, hRenderConfig->roomAcoustics.pAcoustic_rt60, IVAS_REVERB_DEFAULT_S_N_BANDS ); + mvr2r( ivas_reverb_default_small_DSR, hRenderConfig->roomAcoustics.pAcoustic_dsr, IVAS_REVERB_DEFAULT_S_N_BANDS ); + break; + case DEFAULT_REVERB_MEDIUM: + hRenderConfig->roomAcoustics.nBands = IVAS_REVERB_DEFAULT_M_N_BANDS; + hRenderConfig->roomAcoustics.acousticPreDelay = IVAS_REVERB_DEFAULT_M_PRE_DELAY; + hRenderConfig->roomAcoustics.inputPreDelay = IVAS_REVERB_DEFAULT_M_INPUT_DELAY; + hRenderConfig->roomAcoustics.use_er = IVAS_REVERB_DEFAULT_USE_ER; + set_zero( &hRenderConfig->roomAcoustics.pFc_input[0], CLDFB_NO_CHANNELS_MAX ); + set_zero( &hRenderConfig->roomAcoustics.pAcoustic_rt60[0], CLDFB_NO_CHANNELS_MAX ); + set_zero( &hRenderConfig->roomAcoustics.pAcoustic_dsr[0], CLDFB_NO_CHANNELS_MAX ); + + mvr2r( ivas_reverb_default_medium_fc, hRenderConfig->roomAcoustics.pFc_input, IVAS_REVERB_DEFAULT_M_N_BANDS ); + mvr2r( ivas_reverb_default_medium_RT60, hRenderConfig->roomAcoustics.pAcoustic_rt60, IVAS_REVERB_DEFAULT_M_N_BANDS ); + mvr2r( ivas_reverb_default_medium_DSR, hRenderConfig->roomAcoustics.pAcoustic_dsr, IVAS_REVERB_DEFAULT_M_N_BANDS ); + break; + case DEFAULT_REVERB_LARGE: + hRenderConfig->roomAcoustics.nBands = IVAS_REVERB_DEFAULT_L_N_BANDS; + hRenderConfig->roomAcoustics.acousticPreDelay = IVAS_REVERB_DEFAULT_L_PRE_DELAY; + hRenderConfig->roomAcoustics.inputPreDelay = IVAS_REVERB_DEFAULT_L_INPUT_DELAY; + hRenderConfig->roomAcoustics.use_er = IVAS_REVERB_DEFAULT_USE_ER; + set_zero( &hRenderConfig->roomAcoustics.pFc_input[0], CLDFB_NO_CHANNELS_MAX ); + set_zero( &hRenderConfig->roomAcoustics.pAcoustic_rt60[0], CLDFB_NO_CHANNELS_MAX ); + set_zero( &hRenderConfig->roomAcoustics.pAcoustic_dsr[0], CLDFB_NO_CHANNELS_MAX ); + + mvr2r( ivas_reverb_default_large_fc, hRenderConfig->roomAcoustics.pFc_input, IVAS_REVERB_DEFAULT_L_N_BANDS ); + mvr2r( ivas_reverb_default_large_RT60, hRenderConfig->roomAcoustics.pAcoustic_rt60, IVAS_REVERB_DEFAULT_L_N_BANDS ); + mvr2r( ivas_reverb_default_large_DSR, hRenderConfig->roomAcoustics.pAcoustic_dsr, IVAS_REVERB_DEFAULT_L_N_BANDS ); + break; + default: + return IVAS_ERR_ACOUSTIC_ENVIRONMENT_MISSING; + } + + return IVAS_ERR_OK; +} +#endif diff --git a/lib_rend/ivas_rom_rend.c b/lib_rend/ivas_rom_rend.c index 3f4b906bd6fdaa8159f22abe9ed3fb2686c3fd6e..46f29eafa7c19e599d3db1562e265590ca286d7f 100644 --- a/lib_rend/ivas_rom_rend.c +++ b/lib_rend/ivas_rom_rend.c @@ -346,7 +346,79 @@ const float t_design_11_elevation[70] = * Reverberator ROM tables *-----------------------------------------------------------------------*/ -const float ivas_reverb_default_fc[IVAS_REVERB_DEFAULT_N_BANDS] = +#ifdef FIX_1318_ROOM_SIZE_CMD_LINE +const float ivas_reverb_default_small_fc[IVAS_REVERB_DEFAULT_S_N_BANDS] = +{ + 200.0f, 600.0f, 1000.0f, 1400.0f, 1800.0f, 2200.0f, 2600.0f, 3000.0f, 3400.0f, 3800.0f, + 4200.0f, 4600.0f, 5000.0f, 5400.0f, 5800.0f, 6200.0f, 6600.0f, 7000.0f, 7400.0f, 7800.0f, + 8200.0f, 8600.0f, 9000.0f, 9400.0f, 9800.0f, 10200.0f, 10600.0f, 11000.0f, 11400.0f, 11800.0f, + 12200.0f, 12600.0f, 13000.0f, 13400.0f, 13800.0f, 14200.0f, 14600.0f, 15000.0f, 15400.0f, 15800.0f, + 16200.0f, 16600.0f, 17000.0f, 17400.0f, 17800.0f, 18200.0f, 18600.0f, 19000.0f, 19400.0f, 19800.0f, + 20200.0f, 20600.0f, 21000.0f, 21400.0f, 21800.0f, 22200.0f, 22600.0f, 23000.0f, 23400.0f, 23800.0f +}; + +const float ivas_reverb_default_small_RT60[IVAS_REVERB_DEFAULT_S_N_BANDS] = +{ + 0.300000f, 0.273750f, 0.265941f, 0.263784f, 0.265572f, 0.261790f, 0.252988f, 0.245801f, 0.237429f, 0.228169f, + 0.219536f, 0.211116f, 0.203262f, 0.196144f, 0.189161f, 0.182436f, 0.176237f, 0.170114f, 0.164250f, 0.158791f, + 0.153349f, 0.148312f, 0.143266f, 0.138398f, 0.133929f, 0.129493f, 0.125309f, 0.121833f, 0.118321f, 0.115130f, + 0.112655f, 0.109958f, 0.107465f, 0.105311f, 0.103006f, 0.100783f, 0.098629f, 0.096469f, 0.094335f, 0.092217f, + 0.090115f, 0.088057f, 0.086034f, 0.084061f, 0.082327f, 0.080552f, 0.078876f, 0.077614f, 0.076203f, 0.074918f, + 0.074102f, 0.073068f, 0.072153f, 0.071659f, 0.070969f, 0.070686f, 0.070224f, 0.069878f, 0.069936f, 0.069820f +}; + +const float ivas_reverb_default_small_DSR[IVAS_REVERB_DEFAULT_S_N_BANDS] = +{ + 1.562141e-05f, 7.104127e-06f, 4.699859e-06f, 4.302786e-06f, 5.277136e-06f, 6.382504e-06f, 7.237492e-06f, 9.198124e-06f, 1.073813e-05f, 1.148954e-05f, + 1.063691e-05f, 9.580873e-06f, 8.187593e-06f, 7.045559e-06f, 5.871790e-06f, 4.857175e-06f, 4.194530e-06f, 3.594923e-06f, 3.377501e-06f, 4.063327e-06f, + 4.885563e-06f, 6.276646e-06f, 7.591577e-06f, 8.950862e-06f, 9.394771e-06f, 9.701081e-06f, 9.456415e-06f, 8.555601e-06f, 8.035221e-06f, 7.461511e-06f, + 6.976915e-06f, 6.454842e-06f, 5.885498e-06f, 5.657134e-06f, 5.205549e-06f, 4.791783e-06f, 4.635302e-06f, 4.326645e-06f, 4.245139e-06f, 4.107671e-06f, + 4.033808e-06f, 3.961318e-06f, 3.862554e-06f, 3.742024e-06f, 3.559007e-06f, 3.379882e-06f, 3.192690e-06f, 3.129763e-06f, 3.129763e-06f, 3.129763e-06f, + 3.129763e-06f, 3.129763e-06f, 3.129763e-06f, 3.129763e-06f, 3.129763e-06f, 3.129763e-06f, 3.129763e-06f, 3.129763e-06f, 3.129763e-06f, 3.129763e-06f +}; + +const float ivas_reverb_default_medium_fc[IVAS_REVERB_DEFAULT_M_N_BANDS] = +{ + 20.0f, 25.0f, 31.5f, 40.0f, + 50.0f, 63.0f, 80.0f, 100.0f, + 125.0f, 160.0f, 200.0f, 250.0f, + 315.0f, 400.0f, 500.0f, 630.0f, + 800.0f, 1000.0f, 1250.0f, 1600.0f, + 2000.0f, 2500.0f, 3150.0f, 4000.0f, + 5000.0f, 6300.0f, 8000.0f, 10000.0f, + 12500.0f, 16000.0f, 20000.0f +}; + +const float ivas_reverb_default_medium_RT60[IVAS_REVERB_DEFAULT_M_N_BANDS] = +{ + 0.22000000f, 0.22500000f, 0.23150000f, 0.24000000f, + 0.25000000f, 0.26300000f, 0.28000000f, 0.30000000f, + 0.32500000f, 0.36000000f, 0.40000000f, 0.39625000f, + 0.39137500f, 0.38500000f, 0.37750000f, 0.36933070f, + 0.36553800f, 0.36107600f, 0.35953475f, 0.35963200f, + 0.35849250f, 0.34878675f, 0.33447100f, 0.31297400f, + 0.28944200f, 0.26387000f, 0.23550800f, 0.20767000f, + 0.18357975f, 0.16133300f, 0.14229700f +}; + +const float ivas_reverb_default_medium_DSR[IVAS_REVERB_DEFAULT_M_N_BANDS] = +{ + 1.488034e-05f, 1.521853e-05f, 1.565818e-05f, 1.623310e-05f, + 1.690948e-05f, 1.778877e-05f, 1.893862e-05f, 2.029138e-05f, + 2.198233e-05f, 2.434965e-05f, 2.705517e-05f, 2.518051e-05f, + 2.274345e-05f, 1.955652e-05f, 1.580720e-05f, 1.174766e-05f, + 9.989742e-06f, 7.921604e-06f, 7.494128e-06f, 8.064566e-06f, + 9.803470e-06f, 1.171147e-05f, 1.607462e-05f, 1.776450e-05f, + 1.271521e-05f, 6.951610e-06f, 6.154952e-06f, 1.181682e-05f, + 7.084896e-06f, 3.571991e-06f, 2.210372e-06f +}; +#endif + +#ifdef FIX_1318_ROOM_SIZE_CMD_LINE +const float ivas_reverb_default_large_fc[IVAS_REVERB_DEFAULT_L_N_BANDS] = +#else +const float ivas_reverb_default_fc[IVAS_REVERB_DEFAULT_N_BANDS] = +#endif { 20.0f, 25.0f, 31.5f, 40.0f, 50.0f, 63.0f, 80.0f, 100.0f, @@ -358,7 +430,11 @@ const float ivas_reverb_default_fc[IVAS_REVERB_DEFAULT_N_BANDS] = 12500.0f, 16000.0f, 20000.0f }; -const float ivas_reverb_default_RT60[IVAS_REVERB_DEFAULT_N_BANDS] = +#ifdef FIX_1318_ROOM_SIZE_CMD_LINE +const float ivas_reverb_default_large_RT60[IVAS_REVERB_DEFAULT_L_N_BANDS] = +#else +const float ivas_reverb_default_RT60[IVAS_REVERB_DEFAULT_N_BANDS] = +#endif { 1.3622f, 1.4486f, 1.3168f, 1.5787f, 1.4766f, 1.3954f, 1.2889f, 1.3462f, @@ -370,7 +446,11 @@ const float ivas_reverb_default_RT60[IVAS_REVERB_DEFAULT_N_BANDS] = 0.71945f, 0.61682f, 0.60031f }; -const float ivas_reverb_default_DSR[IVAS_REVERB_DEFAULT_N_BANDS] = +#ifdef FIX_1318_ROOM_SIZE_CMD_LINE +const float ivas_reverb_default_large_DSR[IVAS_REVERB_DEFAULT_L_N_BANDS] = +#else +const float ivas_reverb_default_DSR[IVAS_REVERB_DEFAULT_N_BANDS] = +#endif { 1.8811e-08f, 2.1428e-08f, 1.3972e-08f, 1.51e-08f, 1.287e-08f, 1.8747e-08f, 2.413e-08f, 3.9927e-08f, @@ -388,8 +468,8 @@ const float ivas_reverb_default_DSR[IVAS_REVERB_DEFAULT_N_BANDS] = *----------------------------------------------------------------------------------*/ /* CICP1 - Mono */ -const float ls_azimuth_CICP1[1] = { 0.0f }; -const float ls_elevation_CICP1[1] = { 0.0f }; +const float ls_azimuth_CICP1[1] = { 0.0f }; +const float ls_elevation_CICP1[1] = { 0.0f }; /*----------------------------------------------------------------------------------* @@ -619,6 +699,15 @@ const LS_CONVERSION_MATRIX ls_conversion_cicp19_cicp16[] = }; /* Upmix matrices */ +#ifdef FIX_1419_MONO_STEREO_UMX +const LS_CONVERSION_MATRIX ls_conversion_mono_cicpX[] = { + /* First row indicates the number of non-zero elements and the number of matrix columns */ + {1, 12.0f}, + /* Index of non-zero element, value of non-zero element*/ + {2, 1.0f}, +}; + +#endif const LS_CONVERSION_MATRIX ls_conversion_cicp12_cicp14[] = { /* First row indicates the number of non-zero elements and the number of matrix columns */ @@ -704,6 +793,9 @@ const LS_CONVERSION_MATRIX ls_conversion_cicp16_cicp19[] = const LS_CONVERSION_MAPPING ls_conversion_mapping[LS_SETUP_CONVERSION_NUM_MAPPINGS] = { /* Dowmix mappings - NULL is a special case for MONO / STEREO downmix */ +#ifdef FIX_1419_MONO_STEREO_UMX + {IVAS_AUDIO_CONFIG_STEREO, IVAS_AUDIO_CONFIG_MONO, NULL}, +#endif {IVAS_AUDIO_CONFIG_5_1, IVAS_AUDIO_CONFIG_MONO, NULL}, {IVAS_AUDIO_CONFIG_7_1, IVAS_AUDIO_CONFIG_MONO, NULL}, {IVAS_AUDIO_CONFIG_5_1_2, IVAS_AUDIO_CONFIG_MONO, NULL}, @@ -731,6 +823,14 @@ const LS_CONVERSION_MAPPING ls_conversion_mapping[LS_SETUP_CONVERSION_NUM_MAPPIN {IVAS_AUDIO_CONFIG_7_1_4, IVAS_AUDIO_CONFIG_5_1_4, ls_conversion_cicp19_cicp16}, /* Upmix mappings - NULL implies a 1:1 upmix */ +#ifdef FIX_1419_MONO_STEREO_UMX + {IVAS_AUDIO_CONFIG_MONO, IVAS_AUDIO_CONFIG_5_1, ls_conversion_mono_cicpX}, + {IVAS_AUDIO_CONFIG_MONO, IVAS_AUDIO_CONFIG_7_1, ls_conversion_mono_cicpX}, + {IVAS_AUDIO_CONFIG_MONO, IVAS_AUDIO_CONFIG_5_1_2, ls_conversion_mono_cicpX}, + {IVAS_AUDIO_CONFIG_MONO, IVAS_AUDIO_CONFIG_5_1_4, ls_conversion_mono_cicpX}, + {IVAS_AUDIO_CONFIG_MONO, IVAS_AUDIO_CONFIG_7_1_4, ls_conversion_mono_cicpX}, + +#endif {IVAS_AUDIO_CONFIG_STEREO, IVAS_AUDIO_CONFIG_5_1, NULL}, {IVAS_AUDIO_CONFIG_STEREO, IVAS_AUDIO_CONFIG_7_1, NULL}, {IVAS_AUDIO_CONFIG_STEREO, IVAS_AUDIO_CONFIG_5_1_2, NULL}, diff --git a/lib_rend/ivas_rom_rend.h b/lib_rend/ivas_rom_rend.h index 927287ecd96a2b33cb061c32d40013623da77469..9d14bf325fb934af4353306e45edc23833a0752f 100644 --- a/lib_rend/ivas_rom_rend.h +++ b/lib_rend/ivas_rom_rend.h @@ -113,9 +113,24 @@ extern const float t_design_11_elevation[70]; * Reverberator ROM tables *-----------------------------------------------------------------------*/ +#ifdef FIX_1318_ROOM_SIZE_CMD_LINE +extern const float ivas_reverb_default_small_fc[]; +extern const float ivas_reverb_default_small_RT60[]; +extern const float ivas_reverb_default_small_DSR[]; + +extern const float ivas_reverb_default_medium_fc[]; +extern const float ivas_reverb_default_medium_RT60[]; +extern const float ivas_reverb_default_medium_DSR[]; + +extern const float ivas_reverb_default_large_fc[]; +extern const float ivas_reverb_default_large_RT60[]; +extern const float ivas_reverb_default_large_DSR[]; +#else extern const float ivas_reverb_default_fc[]; extern const float ivas_reverb_default_RT60[]; extern const float ivas_reverb_default_DSR[]; +#endif + /*----------------------------------------------------------------------------------* * Renderer SBA & MC enc/dec matrices diff --git a/lib_rend/ivas_rotation.c b/lib_rend/ivas_rotation.c index 95361e116a0128101eb30f9a3d1f73ee0213f0a4..534661af35db3203e7bbadaa2b75b7dc6e1db5e3 100644 --- a/lib_rend/ivas_rotation.c +++ b/lib_rend/ivas_rotation.c @@ -1256,6 +1256,7 @@ ivas_error combine_external_and_head_orientations( } } #endif + return IVAS_ERR_OK; } diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index b0435968b3db7ed6dde714ca9d98e8b7e5c42d69..5f1af59a957b4dba102f471e078059acd3853229 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -93,6 +93,9 @@ typedef struct const int16_t *pSplitRendBFI; const SPLIT_REND_WRAPPER *pSplitRendWrapper; const COMBINED_ORIENTATION_HANDLE *pCombinedOrientationData; +#ifdef FIX_1318_ROOM_SIZE_CMD_LINE + const IVAS_DefaultReverbSize *pSelectedRoomReverbSize; +#endif } rendering_context; /* Common base for input structs */ @@ -105,7 +108,7 @@ typedef struct 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 */ - int32_t delayNumSamples; + int16_t delayNumSamples; } input_base; typedef struct @@ -228,6 +231,9 @@ struct IVAS_REND int8_t rendererConfigEnabled; RENDER_CONFIG_DATA *hRendererConfig; /* Renderer config pointer */ +#ifdef FIX_1318_ROOM_SIZE_CMD_LINE + IVAS_DefaultReverbSize selectedRoomReverbSize; +#endif int16_t num_subframes; hrtf_handles hHrtfs; @@ -1242,6 +1248,9 @@ static rendering_context getRendCtx( ctx.pSplitRendBFI = &hIvasRend->splitRendBFI; ctx.pSplitRendWrapper = hIvasRend->splitRendWrapper; ctx.pCombinedOrientationData = &hIvasRend->hCombinedOrientationData; +#ifdef FIX_1318_ROOM_SIZE_CMD_LINE + ctx.pSelectedRoomReverbSize = &hIvasRend->selectedRoomReverbSize; +#endif return ctx; } @@ -1484,9 +1493,8 @@ static ivas_error alignInputDelay( { ivas_error error; input_ism *inputIsm; - int16_t maxGlobalDelaySamples; - int32_t numSamplesToPush, numSamplesToPop; - uint32_t ringBufferSize, preDelay; + int16_t maxGlobalDelaySamples, numSamplesToPop, numSamplesToPush; + uint16_t ringBufferSize, preDelay; #ifdef FIX_1119_SPLIT_RENDERING_VOIP int16_t i; const float *p_read_channels[MAX_INPUT_CHANNELS]; @@ -1507,7 +1515,7 @@ static ivas_error alignInputDelay( if ( preDelay > 0 ) { - if ( ( error = ivas_TD_RINGBUF_Open( &inputBase->delayBuffer, (int16_t) ringBufferSize, inputAudio.config.numChannels ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_TD_RINGBUF_Open( &inputBase->delayBuffer, ringBufferSize, inputAudio.config.numChannels ) ) != IVAS_ERR_OK ) { return error; } @@ -1515,7 +1523,7 @@ static ivas_error alignInputDelay( /* for the first frame we need to push zeros to align the input delay to the global delay * and then push a frame of actual data */ #ifdef FIX_1119_SPLIT_RENDERING_VOIP - ivas_TD_RINGBUF_PushConstant( inputBase->delayBuffer, 0, (int16_t) preDelay ); + ivas_TD_RINGBUF_PushConstant( inputBase->delayBuffer, 0, preDelay ); #else ivas_TD_RINGBUF_PushZeros( inputBase->delayBuffer, preDelay ); #endif @@ -1538,7 +1546,7 @@ static ivas_error alignInputDelay( /* push in the new input data and pop to retrieve a complete input frame * if we are flushing the inputs, we don't push in any new data */ numSamplesToPush = flushInputs ? 0 : inputAudio.config.numSamplesPerChannel; - numSamplesToPop = flushInputs ? (uint32_t) ivas_TD_RINGBUF_Size( inputBase->delayBuffer ) : (uint32_t) inputAudio.config.numSamplesPerChannel; + numSamplesToPop = flushInputs ? ivas_TD_RINGBUF_Size( inputBase->delayBuffer ) : inputAudio.config.numSamplesPerChannel; #ifdef FIX_1119_SPLIT_RENDERING_VOIP for ( i = 0; i < inputAudio.config.numChannels; ++i ) @@ -3120,6 +3128,9 @@ ivas_error IVAS_REND_Open( hIvasRend->hLimiter = NULL; hIvasRend->efapOutWrapper.hEfap = NULL; hIvasRend->efapOutWrapper.pCustomLsSetup = NULL; +#ifdef FIX_1318_ROOM_SIZE_CMD_LINE + hIvasRend->selectedRoomReverbSize = DEFAULT_REVERB_UNSET; +#endif #ifdef DEBUGGING hIvasRend->numClipping = 0; #endif @@ -3798,6 +3809,85 @@ static ivas_error isar_pre_rend_init( return IVAS_ERR_OK; } +#ifdef FIX_1318_ROOM_SIZE_CMD_LINE +static IVAS_ROOM_SIZE_T getDefaultReverbSize( + input_ism *ismInputs, + input_masa *masaInputs, + input_mc *mcInputs, + input_sba *sbaInputs ) +{ + bool combinedFormat; + int16_t i; + int16_t nActiveInputsIsm, nActiveInputsMasa, nActiveInputsSba, nActiveInputsMc; + IVAS_ROOM_SIZE_T selectedReverb; + selectedReverb = IVAS_ROOM_SIZE_MEDIUM; + + combinedFormat = false; + nActiveInputsIsm = 0; + nActiveInputsMasa = 0; + nActiveInputsMc = 0; + nActiveInputsSba = 0; + + for ( i = 0; i < RENDERER_MAX_ISM_INPUTS; i++ ) + { + if ( ismInputs[i].base.inConfig != IVAS_AUDIO_CONFIG_INVALID ) + { + nActiveInputsIsm++; + } + } + for ( i = 0; i < RENDERER_MAX_MASA_INPUTS; i++ ) + { + if ( masaInputs[i].base.inConfig != IVAS_AUDIO_CONFIG_INVALID ) + { + nActiveInputsMasa++; + } + } + for ( i = 0; i < RENDERER_MAX_MC_INPUTS; i++ ) + { + if ( mcInputs[i].base.inConfig != IVAS_AUDIO_CONFIG_INVALID ) + { + nActiveInputsMc++; + } + } + for ( i = 0; i < RENDERER_MAX_SBA_INPUTS; i++ ) + { + if ( sbaInputs[i].base.inConfig != IVAS_AUDIO_CONFIG_INVALID ) + { + nActiveInputsSba++; + } + } + + /* ISM present with MASA/SBA inputs; treat as combined format */ + if ( nActiveInputsIsm && ( nActiveInputsMasa || nActiveInputsSba ) ) + { + combinedFormat = true; + } + + if ( combinedFormat ) + { + selectedReverb = IVAS_ROOM_SIZE_MEDIUM; + } + else + { + /* Only set large if ISM is present alone */ + if ( nActiveInputsIsm && !nActiveInputsMc ) + { + selectedReverb = IVAS_ROOM_SIZE_LARGE; + } + /* if only MC is present, set medium; Will not be overridden by the subsequent block */ + else if ( nActiveInputsMc ) + { + selectedReverb = IVAS_ROOM_SIZE_MEDIUM; + } + else if ( nActiveInputsMasa || nActiveInputsSba ) + { + selectedReverb = IVAS_ROOM_SIZE_SMALL; + } + } + + return selectedReverb; +} +#endif /*-------------------------------------------------------------------* @@ -3897,6 +3987,18 @@ ivas_error IVAS_REND_AddInput( /* set global maximum delay after adding an input */ setMaxGlobalDelayNs( hIvasRend ); +#ifdef FIX_1318_ROOM_SIZE_CMD_LINE + + /* select default reverb size after adding an input */ + if ( hIvasRend->selectedRoomReverbSize == DEFAULT_REVERB_UNSET ) + { + IVAS_REND_SetReverbRoomSize( hIvasRend, + getDefaultReverbSize( hIvasRend->inputsIsm, + hIvasRend->inputsMasa, + hIvasRend->inputsMc, + hIvasRend->inputsSba ) ); + } +#endif return IVAS_ERR_OK; } @@ -4541,6 +4643,9 @@ ivas_error IVAS_REND_GetRenderConfig( hRCout->renderer_type_override = IVAS_RENDER_TYPE_OVERRIDE_NONE; break; } +#endif +#ifdef IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT + hRCout->roomAcoustics.aeID = hRCin->roomAcoustics.aeID; #endif hRCout->roomAcoustics.nBands = hRCin->roomAcoustics.nBands; hRCout->roomAcoustics.acousticPreDelay = hRCin->roomAcoustics.acousticPreDelay; @@ -4597,6 +4702,9 @@ ivas_error IVAS_REND_FeedRenderConfig( hRenderConfig = hIvasRend->hRendererConfig; #ifdef DEBUGGING hRenderConfig->renderer_type_override = renderConfig.renderer_type_override; +#endif +#ifdef IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT + hRenderConfig->roomAcoustics.aeID = renderConfig.roomAcoustics.aeID; #endif hRenderConfig->roomAcoustics.nBands = renderConfig.roomAcoustics.nBands; hRenderConfig->roomAcoustics.acousticPreDelay = renderConfig.roomAcoustics.acousticPreDelay; @@ -5124,6 +5232,83 @@ ivas_error IVAS_REND_GetCombinedOrientation( return IVAS_ERR_OK; } +#ifdef FIX_1318_ROOM_SIZE_CMD_LINE + +/*---------------------------------------------------------------------* + * IVAS_REND_GetCombinedOrientation() + * + * + *---------------------------------------------------------------------*/ +ivas_error IVAS_REND_GetReverbRoomSize( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + IVAS_ROOM_SIZE_T *reverbRoomSize /* o : Reverb room size */ +) +{ + switch ( hIvasRend->selectedRoomReverbSize ) + { + case DEFAULT_REVERB_SMALL: + *reverbRoomSize = IVAS_ROOM_SIZE_SMALL; + break; + case DEFAULT_REVERB_MEDIUM: + *reverbRoomSize = IVAS_ROOM_SIZE_MEDIUM; + break; + case DEFAULT_REVERB_LARGE: + *reverbRoomSize = IVAS_ROOM_SIZE_LARGE; + break; + case DEFAULT_REVERB_UNSET: + default: + *reverbRoomSize = IVAS_ROOM_SIZE_AUTO; + break; + } + + return IVAS_ERR_OK; +} + +/*---------------------------------------------------------------------* + * IVAS_REND_GetCombinedOrientation() + * + * + *---------------------------------------------------------------------*/ +ivas_error IVAS_REND_SetReverbRoomSize( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const IVAS_ROOM_SIZE_T reverbRoomSize /* i : Reverb room size */ +) +{ + ivas_error error; + + switch ( reverbRoomSize ) + { + case IVAS_ROOM_SIZE_SMALL: + hIvasRend->selectedRoomReverbSize = DEFAULT_REVERB_SMALL; + break; + case IVAS_ROOM_SIZE_MEDIUM: + hIvasRend->selectedRoomReverbSize = DEFAULT_REVERB_MEDIUM; + break; + case IVAS_ROOM_SIZE_LARGE: + hIvasRend->selectedRoomReverbSize = DEFAULT_REVERB_LARGE; + break; + case IVAS_ROOM_SIZE_AUTO: + default: + hIvasRend->selectedRoomReverbSize = DEFAULT_REVERB_UNSET; + break; /* will be setup in IVAS_REND_AddInput() */ + } + + if ( hIvasRend->hRendererConfig != NULL ) + { + if ( ( error = ivas_render_config_change_defaults( hIvasRend->hRendererConfig, hIvasRend->selectedRoomReverbSize ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + return IVAS_ERR_OK; +} + +#endif /*-------------------------------------------------------------------* @@ -8038,7 +8223,12 @@ ivas_error IVAS_REND_GetSplitRendBitstreamHeader( ISAR_SPLIT_REND_CODEC *pCodec, /* o : pointer to codec setting */ ISAR_SPLIT_REND_POSE_CORRECTION_MODE *poseCorrection, /* o : pointer to pose correction mode */ int16_t *pCodec_frame_size_ms, /* o : pointer to codec frame size setting */ - int16_t *pIsar_frame_size_ms /* o : pointer to ISAR frame size setting */ +#ifdef FIX_1437_LC3PLUS_EXTREND_HIRES + int16_t *pIsar_frame_size_ms, /* o : pointer to ISAR frame size setting */ + int16_t *pLc3plusHighRes /* o : pointer to LC3plus High-Res setting */ +#else + int16_t *pIsar_frame_size_ms /* o : pointer to ISAR frame size setting */ +#endif ) { if ( hIvasRend == NULL || hIvasRend->hRendererConfig == NULL ) @@ -8050,6 +8240,9 @@ ivas_error IVAS_REND_GetSplitRendBitstreamHeader( *pCodec_frame_size_ms = hIvasRend->hRendererConfig->split_rend_config.codec_frame_size_ms; *pIsar_frame_size_ms = hIvasRend->hRendererConfig->split_rend_config.isar_frame_size_ms; *poseCorrection = hIvasRend->hRendererConfig->split_rend_config.poseCorrectionMode; +#ifdef FIX_1437_LC3PLUS_EXTREND_HIRES + *pLc3plusHighRes = hIvasRend->hRendererConfig->split_rend_config.lc3plus_highres; +#endif return IVAS_ERR_OK; } diff --git a/lib_rend/lib_rend.h b/lib_rend/lib_rend.h index 4d84f194f9ba18c7127b5e385a52e50de64fe3b7..c4faf090ea362dbf3b40be7d938a31eca54cf29b 100644 --- a/lib_rend/lib_rend.h +++ b/lib_rend/lib_rend.h @@ -261,6 +261,18 @@ ivas_error IVAS_REND_FeedRenderConfig( IVAS_REND_HANDLE hIvasRend, /* i/o: IVAS renderer handle */ const IVAS_RENDER_CONFIG_DATA renderConfig /* i : Render configuration struct */ ); +#ifdef FIX_1318_ROOM_SIZE_CMD_LINE + +ivas_error IVAS_REND_GetReverbRoomSize( + IVAS_REND_HANDLE hIvasRend, /* i/o: IVAS renderer handle */ + IVAS_ROOM_SIZE_T *reverbRoomSize /* o : Reverb room size */ +); + +ivas_error IVAS_REND_SetReverbRoomSize( + IVAS_REND_HANDLE hIvasRend, /* i/o: IVAS renderer handle */ + const IVAS_ROOM_SIZE_T reverbRoomSize /* i : Reverb room size */ +); +#endif ivas_error IVAS_REND_FeedSplitBinauralBitstream( IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ @@ -285,7 +297,12 @@ ivas_error IVAS_REND_GetSplitRendBitstreamHeader( ISAR_SPLIT_REND_CODEC *pCodec, /* o : pointer to codec setting */ ISAR_SPLIT_REND_POSE_CORRECTION_MODE *poseCorrection, /* o : pointer to pose correction mode */ int16_t *pCodec_frame_size_ms, /* o : pointer to codec frame size setting */ +#ifdef FIX_1437_LC3PLUS_EXTREND_HIRES + int16_t *pIsar_frame_size_ms, /* o : pointer to ISAR frame size setting */ + int16_t *pLc3plusHighRes /* o : pointer to LC3plus High-Res setting */ +#else int16_t *pIsar_frame_size_ms /* o : pointer to ISAR frame size setting */ +#endif ); ivas_error IVAS_REND_SetHeadRotation( diff --git a/lib_util/ivas_rtp_api.h b/lib_util/ivas_rtp_api.h index 8e551c5ffcf303a9314a438aaa12eadb7357c086..78fb6144b79a59b0a70508675b759eabba35f17a 100644 --- a/lib_util/ivas_rtp_api.h +++ b/lib_util/ivas_rtp_api.h @@ -272,9 +272,12 @@ typedef enum typedef struct { - bool valid; /* Valid Split Rendering Info for/in the ToC */ - bool diegetic; /* SR content digetic */ - uint32_t bitrateKbps; /* SR bitrate in kbps */ + bool valid; /* Valid Split Rendering Info for/in the ToC */ + bool diegetic; /* SR content digetic */ + uint32_t bitrateKbps; /* SR bitrate in kbps */ +#ifdef RTP_SR_CODEC_FRAME_SIZE_IN_TOC_BYTE + uint32_t codecFrameSizeMs; /* SR transport codec framesize in ms (5/10/20) */ +#endif IVAS_RTP_SR_TRANSPORT codec; /* SR Transport Codec used*/ } IVAS_RTP_SR_INFO; #endif /* RTP_S4_251135_CR26253_0016_REV1 */ @@ -420,9 +423,11 @@ typedef struct IVAS_RTP_UNPACK *IVAS_RTP_UNPACK_HANDLE; /* rtp unpacker handle t typedef struct { uint32_t maxFramesPerPacket; /* maximum no of frame per packet expected during the session */ +#ifndef RTP_SR_CODEC_FRAME_SIZE_IN_TOC_BYTE #ifdef RTP_S4_251135_CR26253_0016_REV1 uint32_t srCodecFrameSizeMs; /* split rendering transport codec frame size in ms (5/10/20) set by sdp negotiation */ #endif +#endif } IVAS_RTP_UNPACK_CONFIG; /* Open an instance of the RTP unpacker and return a handle to rtp unpacker on success diff --git a/lib_util/ivas_rtp_file.c b/lib_util/ivas_rtp_file.c index f7d6d5d86717a7caf5f416ae15513390a8a978de..b8e79fad53158de060083438cabeaac72fe0d7cb 100644 --- a/lib_util/ivas_rtp_file.c +++ b/lib_util/ivas_rtp_file.c @@ -31,6 +31,9 @@ *******************************************************************************************************/ #include #include +#include +#include // stat +#include // bool type #include "ivas_rtp_file.h" #include "ivas_error_utils.h" @@ -46,8 +49,10 @@ static ivas_error IvasRtpFile_Open( IVAS_RTP_FILE_HANDLE *phRtpFile /* o : pointer to an IVAS file reader handle */ ) { - const char *mode = isFileWriter ? "wb" : "rb"; - FILE *f_rtpstream = fopen( filePath, mode ); + FILE *f_rtpstream; + char *mode = isFileWriter ? "wb" : "rb"; + + f_rtpstream = fopen( filePath, mode ); if ( f_rtpstream == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_FILE_OPEN, "could not open: %s\n", filePath ); @@ -152,13 +157,24 @@ void IVAS_RTP_LogPiData( uint32_t nPiDataPresent /* i : Number of valid elements in the piData array */ ) { +#ifdef ISM_PI_DATA + uint16_t n; +#endif uint32_t timestamp = ~0u; if ( f_piDataOut == NULL || piData == NULL || nPiDataPresent == 0 ) { return; } +#if defined IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT || defined ISM_PI_DATA +#ifdef _WIN32 + if ( ftell( f_piDataOut ) > 3 ) +#else if ( ftell( f_piDataOut ) > 2 ) +#endif +#else + if ( ftell( f_piDataOut ) > 2 ) +#endif { fprintf( f_piDataOut, ",\n" ); } @@ -188,7 +204,9 @@ void IVAS_RTP_LogPiData( #ifdef RTP_S4_251135_CR26253_0016_REV1 case IVAS_PI_PLAYBACK_DEVICE_ORIENTATION: case IVAS_PI_HEAD_ORIENTATION: +#ifndef REVERSE_ISM_PI_DATA case IVAS_PI_R_ISM_ORIENTATION: +#endif #endif { fprintf( f_piDataOut, "{\n\t\t\t\"w\": %f,\n\t\t\t\"x\": %f,\n\t\t\t\"y\": %f,\n\t\t\t\"z\": %f \n\t\t}", @@ -214,7 +232,9 @@ void IVAS_RTP_LogPiData( break; #ifdef RTP_S4_251135_CR26253_0016_REV1 case IVAS_PI_LISTENER_POSITION: +#ifndef REVERSE_ISM_PI_DATA case IVAS_PI_R_ISM_POSITION: +#endif { fprintf( f_piDataOut, "{\n\t\t\t\"x\": %f,\n\t\t\t\"y\": %f,\n\t\t\t\"z\": %f \n\t\t}", cur->data.listnerPosition.position.x, cur->data.listnerPosition.position.y, cur->data.listnerPosition.position.z ); @@ -324,6 +344,104 @@ void IVAS_RTP_LogPiData( fprintf( f_piDataOut, "{}" ); } break; +#ifdef ISM_PI_DATA + case IVAS_PI_ISM_ORIENTATION: + { + fprintf( f_piDataOut, "[\n" ); + for ( n = 0; n < cur->data.ismOrientation.numObjects; n++ ) + { + if ( n != 0 ) + { + fprintf( f_piDataOut, ",\n" ); + } + fprintf( f_piDataOut, "\t\t\t{\n\t\t\t\t\"w\": %f,\n\t\t\t\t\"x\": %f,\n\t\t\t\t\"y\": %f,\n\t\t\t\t\"z\": %f \n\t\t\t}", + cur->data.ismOrientation.orientation[n].w, cur->data.ismOrientation.orientation[n].x, cur->data.ismOrientation.orientation[n].y, cur->data.ismOrientation.orientation[n].z ); + } + fprintf( f_piDataOut, "\n\t\t]" ); + } + break; + case IVAS_PI_ISM_NUM: + { + fprintf( f_piDataOut, "{\n" ); + fprintf( f_piDataOut, "\t\t\t\"num\": %d", cur->data.ismNum.numObjects ); + fprintf( f_piDataOut, "\n\t\t}" ); + } + break; + case IVAS_PI_ISM_ID: + { + fprintf( f_piDataOut, "{\n" ); + fprintf( f_piDataOut, "\t\t\t\"ids\": [\n" ); + for ( n = 0; n < cur->data.ismId.numObjects; n++ ) + { + if ( n != 0 ) + { + fprintf( f_piDataOut, ",\n" ); + } + fprintf( f_piDataOut, "\t\t\t\t%d", cur->data.ismId.id[n] ); + } + fprintf( f_piDataOut, "\n\t\t\t]" ); + fprintf( f_piDataOut, "\n\t\t}" ); + } + break; + case IVAS_PI_ISM_GAIN: + { + fprintf( f_piDataOut, "{\n" ); + fprintf( f_piDataOut, "\t\t\t\"gains\": [\n" ); + for ( n = 0; n < cur->data.ismGain.numObjects; n++ ) + { + if ( n != 0 ) + { + fprintf( f_piDataOut, ",\n" ); + } + fprintf( f_piDataOut, "\t\t\t\t%d", cur->data.ismGain.dB[n] ); + } + fprintf( f_piDataOut, "\n\t\t\t]" ); + fprintf( f_piDataOut, "\n\t\t}" ); + } + break; + case IVAS_PI_ISM_POSITION: + { + fprintf( f_piDataOut, "[\n" ); + for ( n = 0; n < cur->data.ismPosition.numObjects; n++ ) + { + if ( n != 0 ) + { + fprintf( f_piDataOut, ",\n" ); + } + fprintf( f_piDataOut, "\t\t\t{\n\t\t\t\t\"x\": %f,\n\t\t\t\t\"y\": %f,\n\t\t\t\t\"z\": %f \n\t\t\t}", cur->data.ismPosition.position[n].x, cur->data.ismPosition.position[n].y, cur->data.ismPosition.position[n].z ); + } + fprintf( f_piDataOut, "\n\t\t]" ); + } + break; + case IVAS_PI_ISM_DISTANCE_ATTENUATION: + { + fprintf( f_piDataOut, "[\n" ); + for ( n = 0; n < cur->data.ismAttenuation.numObjects; n++ ) + { + if ( n != 0 ) + { + fprintf( f_piDataOut, ",\n" ); + } + fprintf( f_piDataOut, "\t\t\t{\n\t\t\t\t\"ref_dist\": %f,\n\t\t\t\t\"max_dist\": %f,\n\t\t\t\t\"roll_off\": %f \n\t\t\t}", cur->data.ismAttenuation.distAtten[n].ref_dist, cur->data.ismAttenuation.distAtten[n].max_dist, cur->data.ismAttenuation.distAtten[n].roll ); + } + fprintf( f_piDataOut, "\n\t\t]" ); + } + break; + case IVAS_PI_ISM_DIRECTIVITY: + { + fprintf( f_piDataOut, "[\n" ); + for ( n = 0; n < cur->data.ismDirectivity.numObjects; n++ ) + { + if ( n != 0 ) + { + fprintf( f_piDataOut, ",\n" ); + } + fprintf( f_piDataOut, "\t\t\t{\n\t\t\t\t\"inner_ang\": %d,\n\t\t\t\t\"outer_ang\": %d,\n\t\t\t\t\"outer_att\": %f \n\t\t\t}", cur->data.ismDirectivity.directivity[n].innerConeAngle, cur->data.ismDirectivity.directivity[n].outerConeAngle, cur->data.ismDirectivity.directivity[n].outerAttenuationdB ); + } + fprintf( f_piDataOut, "\n\t\t]" ); + } + break; +#else case IVAS_PI_ISM_NUM: case IVAS_PI_ISM_ID: case IVAS_PI_ISM_GAIN: @@ -331,10 +449,57 @@ void IVAS_RTP_LogPiData( case IVAS_PI_ISM_POSITION: case IVAS_PI_ISM_DISTANCE_ATTENUATION: case IVAS_PI_ISM_DIRECTIVITY: + { + fprintf( f_piDataOut, "{}" ); + } + break; +#endif case IVAS_PI_PI_LATENCY: + { + fprintf( f_piDataOut, "{" ); + fprintf( f_piDataOut, "\n\t\t\t\"reverseType\": \"%s\",", PiDataNames[cur->data.piLatency.type] ); + fprintf( f_piDataOut, "\n\t\t\t\"latency\": %d", cur->data.piLatency.latency ); + fprintf( f_piDataOut, "\n\t\t}" ); + } + break; case IVAS_PI_R_ISM_ID: +#ifdef REVERSE_ISM_PI_DATA + { + fprintf( f_piDataOut, "{\n" ); + fprintf( f_piDataOut, "\t\t\t\"id\": %d", cur->data.ismEditId.id ); + fprintf( f_piDataOut, "\n\t\t}" ); + } + break; +#endif case IVAS_PI_R_ISM_GAIN: +#ifdef REVERSE_ISM_PI_DATA + { + fprintf( f_piDataOut, "{\n" ); + fprintf( f_piDataOut, "\t\t\t\"gain\": %d", cur->data.ismEditGain.dB ); + fprintf( f_piDataOut, "\n\t\t}" ); + } + break; + case IVAS_PI_R_ISM_ORIENTATION: + { + fprintf( f_piDataOut, "{\n\t\t\t\"w\": %f,\n\t\t\t\"x\": %f,\n\t\t\t\"y\": %f,\n\t\t\t\"z\": %f \n\t\t}", + cur->data.ismEditOrientation.orientation.w, cur->data.ismEditOrientation.orientation.x, cur->data.ismEditOrientation.orientation.y, cur->data.ismEditOrientation.orientation.z ); + } + break; + case IVAS_PI_R_ISM_POSITION: + { + fprintf( f_piDataOut, "{\n\t\t\t\"x\": %f,\n\t\t\t\"y\": %f,\n\t\t\t\"z\": %f \n\t\t}", + cur->data.ismEditPosition.position.x, cur->data.ismEditPosition.position.y, cur->data.ismEditPosition.position.z ); + } + break; +#endif case IVAS_PI_R_ISM_DIRECTION: +#ifdef REVERSE_ISM_PI_DATA + { + fprintf( f_piDataOut, "{\n\t\t\t\"azi\": %f,\n\t\t\t\"elev\": %f \n\t\t}", + cur->data.ismEditDirection.azimuth, cur->data.ismEditDirection.elevation ); + } + break; +#endif #endif /* RTP_S4_251135_CR26253_0016_REV1 */ case IVAS_PI_NO_DATA: { @@ -558,7 +723,7 @@ void IVAS_RTP_WriteExtPiData( break; case IVAS_PI_PI_LATENCY: { - fprintf( f_piDataOut, "%d", cur->data.piLatency.latency ); + fprintf( f_piDataOut, "%s,%d", PiDataNames[cur->data.piLatency.type], cur->data.piLatency.latency ); } break; case IVAS_PI_R_ISM_ID: @@ -706,8 +871,10 @@ ivas_error IVAS_RTP_WRITER_Init( ivas_error IVAS_RTP_READER_Init( IVAS_RTP *rtp, /* i/o : IVAS RTP File reader handle */ +#ifndef RTP_SR_CODEC_FRAME_SIZE_IN_TOC_BYTE #ifdef RTP_S4_251135_CR26253_0016_REV1 uint32_t srCodecFrameSizeMs, /* i : SR Codec Framesize in ms */ +#endif #endif const char *inputBitstreamFilename, /* i : Input rtpdump filename */ const char *piOutputFilename, /* i : Output PI data json filename */ @@ -720,7 +887,9 @@ ivas_error IVAS_RTP_READER_Init( memset( rtp, 0, sizeof( IVAS_RTP ) ); rtp->unpackCfg.maxFramesPerPacket = IVAS_MAX_FRAMES_PER_RTP_PACKET; +#ifndef RTP_SR_CODEC_FRAME_SIZE_IN_TOC_BYTE rtp->unpackCfg.srCodecFrameSizeMs = srCodecFrameSizeMs; +#endif rtp->rtpPacket.buffer = rtp->packet; rtp->rtpPacket.capacity = sizeof( rtp->packet ); @@ -934,3 +1103,10 @@ ivas_error IVAS_RTP_ReadNextFrame( return IVAS_ERR_OK; } + +uint16_t IVAS_RTP_OwnRandom( uint16_t *seed ) +{ + *seed = (uint16_t) ( *seed * 31821L + 13849L ); + + return ( *seed ); +} diff --git a/lib_util/ivas_rtp_file.h b/lib_util/ivas_rtp_file.h index 70f8c99f0e076eaf4d4c9633513864bfbe6e763e..b57d387cf449846fb24dc2257669b93f1f9466d1 100644 --- a/lib_util/ivas_rtp_file.h +++ b/lib_util/ivas_rtp_file.h @@ -75,8 +75,10 @@ ivas_error IVAS_RTP_WRITER_Init( IVAS_RTP *rtp, const char *outputBitstreamFilen #else ivas_error IVAS_RTP_WRITER_Init( IVAS_RTP *rtp, const char *outputBitstreamFilename, uint32_t numFramesPerPacket ); #endif +#ifndef RTP_SR_CODEC_FRAME_SIZE_IN_TOC_BYTE #ifdef RTP_S4_251135_CR26253_0016_REV1 ivas_error IVAS_RTP_READER_Init( IVAS_RTP *rtp, uint32_t srCodecFrameSizeMs, const char *inputBitstreamFilename, const char *piOutputFilename, bool isExtOutput, const char *outputWavFilename ); +#endif #else ivas_error IVAS_RTP_READER_Init( IVAS_RTP *rtp, const char *inputBitstreamFilename, const char *piOutputFilename, bool isExtOutput, const char *outputWavFilename ); #endif @@ -91,5 +93,6 @@ ivas_error IVAS_RTP_ReadNextFrame( IVAS_RTP *rtp, uint8_t *au, int16_t *auSizeBi void IVAS_RTP_LogPiData( FILE *f_piDataOut, const PIDATA_TS *piData, uint32_t nPiDataPresent ); void IVAS_RTP_WriteExtPiData( FILE *f_piDataOut, const PIDATA_TS *piData, uint32_t nPiDataPresent, uint16_t numObj ); const char *IVAS_RTP_GetExtPiFilePath( IVAS_RTP *rtp ); +uint16_t IVAS_RTP_OwnRandom( uint16_t *seed ); #endif /* IVAS_RTP_FILE_H */ diff --git a/lib_util/ivas_rtp_internal.h b/lib_util/ivas_rtp_internal.h index dc3dd9c1292ced08e6e6edd6b2b0b30a8d917fe2..a550892548f3b0d82815ca935562b13c8a23d306 100644 --- a/lib_util/ivas_rtp_internal.h +++ b/lib_util/ivas_rtp_internal.h @@ -48,6 +48,9 @@ enum MASK_BITS MASK_6BIT = 0x3F, MASK_7BIT = 0x7F, MASK_8BIT = 0xFF, +#ifdef REVERSE_ISM_PI_DATA + MASK_9BIT = 0x1FF, +#endif }; diff --git a/lib_util/ivas_rtp_payload.c b/lib_util/ivas_rtp_payload.c index 98846adf847ea0b9cd930dd35ee18abd03f14564..0398d9ce401ff633a1b52d48b5533e0daeb193eb 100644 --- a/lib_util/ivas_rtp_payload.c +++ b/lib_util/ivas_rtp_payload.c @@ -852,7 +852,16 @@ static ivas_error getSRToCByte( uint8_t *tocByte /* o : toc byte 2 */ ) { +#ifdef RTP_SR_CODEC_FRAME_SIZE_IN_TOC_BYTE + uint8_t bitIdx, codecId, digetic, codecFrameSize; + + if ( srInfo->codecFrameSizeMs != 5 && srInfo->codecFrameSizeMs != 10 && srInfo->codecFrameSizeMs != 20 ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Unsupported codec framesize for SR provided" ); + } +#else uint8_t bitIdx, codecId, digetic; +#endif if ( srInfo->bitrateKbps < 256000 || srInfo->bitrateKbps > 512000 ) { return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Unsupported bitrate for SR" ); @@ -862,7 +871,12 @@ static ivas_error getSRToCByte( codecId = (uint8_t) srInfo->codec; digetic = srInfo->diegetic ? 1 : 0; +#ifdef RTP_SR_CODEC_FRAME_SIZE_IN_TOC_BYTE + codecFrameSize = ( srInfo->codecFrameSizeMs == 20 ) ? 3 : (uint8_t) ( srInfo->codecFrameSizeMs / 5 ); + *tocByte = ( digetic << 6 ) | ( codecId << 5 ) | ( bitIdx << 3 ) | ( codecFrameSize << 1 ); +#else *tocByte = ( digetic << 6 ) | ( codecId << 5 ) | ( bitIdx << 3 ); +#endif return IVAS_ERR_OK; } @@ -1412,8 +1426,10 @@ static uint32_t parseSubsequentEByte( const IVAS_DATA_BUFFER *payload, uint32_t return nBytes; } +#ifndef RTP_SR_CODEC_FRAME_SIZE_IN_TOC_BYTE #ifdef RTP_S4_251135_CR26253_0016_REV1 static ivas_error parseToCByte( const IVAS_DATA_BUFFER *payload, uint32_t *numBytes, uint32_t *numFrames, TOC_INFO *toc, uint32_t maxNumberOfToCBytes, uint32_t srCodecFrameSizeMs ) +#endif #else static ivas_error parseToCByte( const IVAS_DATA_BUFFER *payload, uint32_t *numBytes, uint32_t *numFrames, TOC_INFO *toc, uint32_t maxNumberOfToCBytes ) #endif @@ -1474,6 +1490,9 @@ static ivas_error parseToCByte( const IVAS_DATA_BUFFER *payload, uint32_t *numBy if ( nBytes < payload->length ) { uint8_t SR_BR; +#ifdef RTP_SR_CODEC_FRAME_SIZE_IN_TOC_BYTE + static const uint8_t codecFrameSizeMap[4] = { 0, 5, 10, 20 }; +#endif byte = payload->buffer[nBytes++]; SR_BR = ( byte >> 3 ) & MASK_2BIT; if ( SR_BR == 0 ) @@ -1484,7 +1503,12 @@ static ivas_error parseToCByte( const IVAS_DATA_BUFFER *payload, uint32_t *numBy toc->srInfo.diegetic = ( byte >> 6 ) & MASK_1BIT; toc->srInfo.codec = IVAS_SR_TRANSPORT_LCLD + ( ( byte >> 5 ) & MASK_1BIT ); toc->srInfo.bitrateKbps = ( SR_BR + 1 ) * 128000u; +#ifdef RTP_SR_CODEC_FRAME_SIZE_IN_TOC_BYTE + toc->srInfo.codecFrameSizeMs = codecFrameSizeMap[( byte >> 1 ) & MASK_2BIT]; + toc->auNumBits = toc->srInfo.bitrateKbps * toc->srInfo.codecFrameSizeMs / 1000; +#else toc->auNumBits = toc->srInfo.bitrateKbps * srCodecFrameSizeMs / 1000; +#endif } else { @@ -1667,8 +1691,10 @@ ivas_error IVAS_RTP_UNPACK_PushPayload( /* Unpack the ToC Bytes => Extract number of frames in packet */ +#ifndef RTP_SR_CODEC_FRAME_SIZE_IN_TOC_BYTE #ifdef RTP_S4_251135_CR26253_0016_REV1 error = parseToCByte( payload, &nBytes, &numFrames, toc, sizeof( toc ) / sizeof( toc[0] ), hUnpack->initConfig.srCodecFrameSizeMs ); +#endif #else error = parseToCByte( payload, &nBytes, &numFrames, toc, sizeof( toc ) / sizeof( toc[0] ) ); #endif diff --git a/lib_util/ivas_rtp_pi_data.c b/lib_util/ivas_rtp_pi_data.c index 8db9d41f9df241e317cdcf606e0fcc682c4a0a8c..b9b7bcc7e44fbd19ca75570c793acd9e697bc588 100644 --- a/lib_util/ivas_rtp_pi_data.c +++ b/lib_util/ivas_rtp_pi_data.c @@ -32,6 +32,21 @@ #include "ivas_error_utils.h" #include "ivas_rtp_internal.h" +#ifdef REVERSE_ISM_PI_DATA +#include +#endif +#ifdef ISM_PI_DATA +#include + +#ifndef min +#define min( x, y ) ( ( x ) < ( y ) ? ( x ) : ( y ) ) +#endif + +#ifndef max +#define max( x, y ) ( ( x ) > ( y ) ? ( x ) : ( y ) ) +#endif + +#endif #ifdef IVAS_RTPDUMP @@ -154,6 +169,43 @@ static ivas_error packOrientation( const IVAS_PIDATA_GENERIC *piData, uint8_t *b return IVAS_ERR_OK; } +#ifdef ISM_PI_DATA +static ivas_error packISMOrientation( const IVAS_PIDATA_GENERIC *piData, uint8_t *buffer, uint32_t maxDataBytes, uint32_t *nBytesWritten ) +{ + uint32_t nBytes = 0; + const IVAS_PIDATA_ISM_ORIENTATION *orientation = (const IVAS_PIDATA_ISM_ORIENTATION *) piData; + uint16_t n; + *nBytesWritten = 0; + + if ( piData->size != sizeof( IVAS_PIDATA_ISM_ORIENTATION ) ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect size in Orientation PI data" ); + } + + if ( piData->piDataType != IVAS_PI_ISM_ORIENTATION ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect PI ID in Orientation PI data" ); + } + /* Orientation data is 8 bytes, header is 2 bytes */ + if ( maxDataBytes < 8 * IVAS_MAX_NUM_OBJECTS + 2 ) + { + return IVAS_ERROR( IVAS_ERR_RTP_INSUFFICIENT_OUTPUT_SIZE, "Insufficient space to pack Orientation PI data" ); + } + + buffer[nBytes++] = ( orientation->piDataType & MASK_5BIT ); /* PF/PM populated during final packing */ + buffer[nBytes++] = (uint8_t) orientation->numObjects * 8; + for ( n = 0; n < orientation->numObjects; n++ ) + { + nBytes = writeInt16( buffer, nBytes, ivasPayload_convertToQ15( orientation->orientation[n].w ) ); + nBytes = writeInt16( buffer, nBytes, ivasPayload_convertToQ15( orientation->orientation[n].x ) ); + nBytes = writeInt16( buffer, nBytes, ivasPayload_convertToQ15( orientation->orientation[n].y ) ); + nBytes = writeInt16( buffer, nBytes, ivasPayload_convertToQ15( orientation->orientation[n].z ) ); + } + *nBytesWritten = nBytes; + return IVAS_ERR_OK; +} +#endif + static ivas_error unpackOrientation( const uint8_t *buffer, uint32_t numDataBytes, IVAS_PIDATA_GENERIC *piData ) { IVAS_PIDATA_ORIENTATION *orientation = (IVAS_PIDATA_ORIENTATION *) piData; @@ -173,6 +225,40 @@ static ivas_error unpackOrientation( const uint8_t *buffer, uint32_t numDataByte return IVAS_ERR_OK; } +#ifdef ISM_PI_DATA +static ivas_error unpackISMOrientation( const uint8_t *buffer, uint32_t numDataBytes, IVAS_PIDATA_GENERIC *piData ) +{ + IVAS_PIDATA_ISM_ORIENTATION *ism_orientation = (IVAS_PIDATA_ISM_ORIENTATION *) piData; + + /* Orientation data is 8 bytes */ + uint16_t n; + if ( numDataBytes % 8 != 0 ) + { + return IVAS_ERROR( IVAS_ERR_RTP_UNPACK_PI_DATA, "Incorrect size to unpack Orientation PI data" ); + } + + ism_orientation->size = sizeof( IVAS_PIDATA_ISM_ORIENTATION ); + ism_orientation->numObjects = (uint16_t) numDataBytes / 8; + + for ( n = 0; n < ism_orientation->numObjects; n++ ) + { + ism_orientation->orientation[n].w = FLOAT_FROM_Q15( readInt16( &buffer[8 * n] ) ); + ism_orientation->orientation[n].x = FLOAT_FROM_Q15( readInt16( &buffer[8 * n + 2] ) ); + ism_orientation->orientation[n].y = FLOAT_FROM_Q15( readInt16( &buffer[8 * n + 4] ) ); + ism_orientation->orientation[n].z = FLOAT_FROM_Q15( readInt16( &buffer[8 * n + 6] ) ); + } + for ( ; n < IVAS_MAX_NUM_OBJECTS; n++ ) + { + ism_orientation->orientation[n].w = 0.0f; + ism_orientation->orientation[n].x = 0.0f; + ism_orientation->orientation[n].y = 0.0f; + ism_orientation->orientation[n].z = 0.0f; + } + + return IVAS_ERR_OK; +} +#endif + static uint32_t getIndexTable( const float *table, uint32_t tableLength, float value ) { uint32_t idx = 0; @@ -427,6 +513,56 @@ static ivas_error unpackDynamicSuppression( const uint8_t *buffer, uint32_t numD return IVAS_ERR_OK; } +#ifdef REVERSE_ISM_PI_DATA +static ivas_error packPosition( const IVAS_PIDATA_GENERIC *piData, uint8_t *buffer, uint32_t maxDataBytes, uint32_t *nBytesWritten ) +{ + uint32_t nBytes = 0; + const IVAS_PIDATA_POSITION *position = (const IVAS_PIDATA_POSITION *) piData; + + *nBytesWritten = 0; + + if ( piData->size != sizeof( IVAS_PIDATA_POSITION ) ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect size in position PI data" ); + } + + if ( piData->piDataType != IVAS_PI_LISTENER_POSITION && piData->piDataType != IVAS_PI_R_ISM_POSITION ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect PI ID in position PI data" ); + } + + /* Position data is 6 bytes, header is 2 bytes */ + if ( maxDataBytes < 6 + 2 ) + { + return IVAS_ERROR( IVAS_ERR_RTP_INSUFFICIENT_OUTPUT_SIZE, "Insufficient space to pack position PI data" ); + } + + buffer[nBytes++] = ( position->piDataType & MASK_5BIT ); /* PF/PM populated during final packing */ + buffer[nBytes++] = 6; + nBytes = writeInt16( buffer, nBytes, ivasPayload_convertToQ15( position->position.x / MAX_PI_POSITION_METERS ) ); + nBytes = writeInt16( buffer, nBytes, ivasPayload_convertToQ15( position->position.y / MAX_PI_POSITION_METERS ) ); + nBytes = writeInt16( buffer, nBytes, ivasPayload_convertToQ15( position->position.z / MAX_PI_POSITION_METERS ) ); + *nBytesWritten = nBytes; + return IVAS_ERR_OK; +} + +static ivas_error unpackPosition( const uint8_t *buffer, uint32_t numDataBytes, IVAS_PIDATA_GENERIC *piData ) +{ + IVAS_PIDATA_POSITION *position = (IVAS_PIDATA_POSITION *) piData; + + /* Position data is 6 bytes */ + if ( numDataBytes != 6 ) + { + return IVAS_ERROR( IVAS_ERR_RTP_UNPACK_PI_DATA, "Incorrect size to unpack position PI data" ); + } + + position->size = sizeof( IVAS_PIDATA_POSITION ); + position->position.x = FLOAT_FROM_Q15( readInt16( &buffer[0] ) ) * MAX_PI_POSITION_METERS; + position->position.y = FLOAT_FROM_Q15( readInt16( &buffer[2] ) ) * MAX_PI_POSITION_METERS; + position->position.z = FLOAT_FROM_Q15( readInt16( &buffer[4] ) ) * MAX_PI_POSITION_METERS; + return IVAS_ERR_OK; +} +#else static ivas_error packListenerPosition( const IVAS_PIDATA_GENERIC *piData, uint8_t *buffer, uint32_t maxDataBytes, uint32_t *nBytesWritten ) { uint32_t nBytes = 0; @@ -476,6 +612,68 @@ static ivas_error unpackListenerPosition( const uint8_t *buffer, uint32_t numDat listener->position.z = FLOAT_FROM_Q15( readInt16( &buffer[4] ) ) * MAX_PI_POSITION_METERS; return IVAS_ERR_OK; } +#endif + +#ifdef ISM_PI_DATA +static ivas_error packISMPosition( const IVAS_PIDATA_GENERIC *piData, uint8_t *buffer, uint32_t maxDataBytes, uint32_t *nBytesWritten ) +{ + uint32_t nBytes = 0, n; + const IVAS_PIDATA_ISM_POSITION *ism_position = (const IVAS_PIDATA_ISM_POSITION *) piData; + + *nBytesWritten = 0; + + if ( piData->size != sizeof( IVAS_PIDATA_ISM_POSITION ) ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect size in ISM POSITION PI data" ); + } + + if ( piData->piDataType != IVAS_PI_ISM_POSITION ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect PI ID in ISM POSITION PI data" ); + } + + /* Position data is 6 bytes, header is 2 bytes */ + if ( maxDataBytes < 6 * IVAS_MAX_NUM_OBJECTS + 2 ) + { + return IVAS_ERROR( IVAS_ERR_RTP_INSUFFICIENT_OUTPUT_SIZE, "Insufficient space to pack ISM POSITION PI data" ); + } + + buffer[nBytes++] = ( ism_position->piDataType & MASK_5BIT ); /* PF/PM populated during final packing */ + buffer[nBytes++] = (uint8_t) ism_position->numObjects * 6; + for ( n = 0; n < ism_position->numObjects; n++ ) + { + nBytes = writeInt16( buffer, nBytes, ivasPayload_convertToQ15( ism_position->position[n].x / MAX_PI_POSITION_METERS ) ); + nBytes = writeInt16( buffer, nBytes, ivasPayload_convertToQ15( ism_position->position[n].y / MAX_PI_POSITION_METERS ) ); + nBytes = writeInt16( buffer, nBytes, ivasPayload_convertToQ15( ism_position->position[n].z / MAX_PI_POSITION_METERS ) ); + } + *nBytesWritten = nBytes; + return IVAS_ERR_OK; +} + +static ivas_error unpackISMPosition( const uint8_t *buffer, uint32_t numDataBytes, IVAS_PIDATA_GENERIC *piData ) +{ + uint16_t n; + IVAS_PIDATA_ISM_POSITION *ism_position = (IVAS_PIDATA_ISM_POSITION *) piData; + + /* Position data is 6 bytes */ + if ( numDataBytes % 6 != 0 ) + { + return IVAS_ERROR( IVAS_ERR_RTP_UNPACK_PI_DATA, "Incorrect size to unpack LISTENER POSITION PI data" ); + } + + ism_position->size = sizeof( IVAS_PIDATA_ISM_POSITION ); + ism_position->piDataType = IVAS_PI_ISM_POSITION; + ism_position->numObjects = (uint16_t) numDataBytes / 6; + + for ( n = 0; n < ism_position->numObjects; n++ ) + { + ism_position->position[n].x = FLOAT_FROM_Q15( readInt16( &buffer[6 * n] ) ) * MAX_PI_POSITION_METERS; + ism_position->position[n].y = FLOAT_FROM_Q15( readInt16( &buffer[6 * n + 2] ) ) * MAX_PI_POSITION_METERS; + ism_position->position[n].z = FLOAT_FROM_Q15( readInt16( &buffer[6 * n + 4] ) ) * MAX_PI_POSITION_METERS; + } + return IVAS_ERR_OK; +} +#endif static ivas_error packDiegetic( const IVAS_PIDATA_GENERIC *piData, uint8_t *buffer, uint32_t maxDataBytes, uint32_t *nBytesWritten ) { @@ -629,7 +827,627 @@ static ivas_error unpackAudioFocusCommon( const uint8_t *buffer, uint32_t numDat return IVAS_ERR_OK; } +#ifdef ISM_PI_DATA +static ivas_error packISMNum( const IVAS_PIDATA_GENERIC *piData, uint8_t *buffer, uint32_t maxDataBytes, uint32_t *nBytesWritten ) +{ + uint32_t nBytes = 0; + const IVAS_PIDATA_ISM_NUM *ism_num = (const IVAS_PIDATA_ISM_NUM *) piData; + + *nBytesWritten = 0; + + if ( piData->size != sizeof( IVAS_PIDATA_ISM_NUM ) ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect size in ISM_NUM PI data" ); + } + + if ( piData->piDataType != IVAS_PI_ISM_NUM ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect PI ID in ISM_NUM PI data" ); + } + + /* ISM_NUM data is 1 bytes, header is 2 bytes */ + if ( maxDataBytes < 1 + 2 ) + { + return IVAS_ERROR( IVAS_ERR_RTP_INSUFFICIENT_OUTPUT_SIZE, "Insufficient space to pack ISM_NUM PI data" ); + } + + buffer[nBytes++] = ( ism_num->piDataType & MASK_5BIT ); /* PF/PM populated during final packing */ + buffer[nBytes++] = 1; + buffer[nBytes++] = ( ( ism_num->numObjects - 1 ) & MASK_2BIT ) << 6; + *nBytesWritten = nBytes; + return IVAS_ERR_OK; +} + +static ivas_error unpackISMNum( const uint8_t *buffer, uint32_t numDataBytes, IVAS_PIDATA_GENERIC *piData ) +{ + IVAS_PIDATA_ISM_NUM *ism_num = (IVAS_PIDATA_ISM_NUM *) piData; + uint8_t byte; + + /* ISM_NUM data is 1 bytes */ + if ( numDataBytes != 1 ) + { + return IVAS_ERROR( IVAS_ERR_RTP_UNPACK_PI_DATA, "Incorrect size to unpack ISM_NUM PI data" ); + } + + ism_num->size = sizeof( IVAS_PIDATA_ISM_NUM ); + ism_num->piDataType = IVAS_PI_ISM_NUM; + + byte = buffer[0]; + ism_num->numObjects = ( ( byte >> 6 ) & MASK_2BIT ) + 1; + return IVAS_ERR_OK; +} +static ivas_error packISMID( const IVAS_PIDATA_GENERIC *piData, uint8_t *buffer, uint32_t maxDataBytes, uint32_t *nBytesWritten ) +{ + uint32_t nBytes = 0, n; + const IVAS_PIDATA_ISM_ID *ism_id = (const IVAS_PIDATA_ISM_ID *) piData; + + *nBytesWritten = 0; + + if ( piData->size > sizeof( IVAS_PIDATA_ISM_ID ) ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect size in ISM_ID PI data" ); + } + + if ( piData->piDataType != IVAS_PI_ISM_ID ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect PI ID in ISM_ID PI data" ); + } + + /* ISM_ID data is 1 byte per object, header is 2 bytes */ + if ( maxDataBytes < 1 * IVAS_MAX_NUM_OBJECTS + 2 ) + { + return IVAS_ERROR( IVAS_ERR_RTP_INSUFFICIENT_OUTPUT_SIZE, "Insufficient space to pack ISM_NUM PI data" ); + } + + buffer[nBytes++] = ( ism_id->piDataType & MASK_5BIT ); /* PF/PM populated during final packing */ + buffer[nBytes++] = (uint8_t) ism_id->numObjects; + /* Pack ID for each object */ + for ( n = 0; n < ism_id->numObjects; n++ ) + { + buffer[nBytes++] = ( ism_id->id[n] & MASK_8BIT ); + } + *nBytesWritten = nBytes; + return IVAS_ERR_OK; +} + +static ivas_error unpackISMID( const uint8_t *buffer, uint32_t numDataBytes, IVAS_PIDATA_GENERIC *piData ) +{ + uint32_t n; + IVAS_PIDATA_ISM_ID *ism_id = (IVAS_PIDATA_ISM_ID *) piData; + + /* ISM_ID data is 1 byte per object */ + if ( numDataBytes > IVAS_MAX_NUM_OBJECTS ) + { + return IVAS_ERROR( IVAS_ERR_RTP_UNPACK_PI_DATA, "Incorrect size to unpack ISM_ID PI data" ); + } + + ism_id->size = sizeof( IVAS_PIDATA_ISM_ID ); + ism_id->piDataType = IVAS_PI_ISM_ID; + ism_id->numObjects = (uint16_t) numDataBytes; + + /* Unpack ID for each object (1 byte each) */ + for ( n = 0; n < ism_id->numObjects; n++ ) + { + ism_id->id[n] = buffer[n]; + } + for ( ; n < IVAS_MAX_NUM_OBJECTS; n++ ) + { + ism_id->id[n] = 0; /* Initializing to 0, although there might be another object with this ID */ + } + + return IVAS_ERR_OK; +} +#endif +#ifdef PI_LATENCY +static ivas_error packPiLatency( const IVAS_PIDATA_GENERIC *piData, uint8_t *buffer, uint32_t maxDataBytes, uint32_t *nBytesWritten ) +{ + uint32_t typeBits; + uint32_t latencyBits; + uint32_t word; + uint32_t nBytes = 0; + const IVAS_PIDATA_REVERSE_PI_LATENCY *p = (const IVAS_PIDATA_REVERSE_PI_LATENCY *) piData; + + *nBytesWritten = 0; + if ( piData->size != sizeof( IVAS_PIDATA_REVERSE_PI_LATENCY ) ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect size for PI_LATENCY data" ); + } + if ( piData->piDataType != IVAS_PI_PI_LATENCY ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect PI ID for PI_LATENCY data" ); + } + if ( maxDataBytes < 2 + 4 ) + { + return IVAS_ERROR( IVAS_ERR_RTP_INSUFFICIENT_OUTPUT_SIZE, "Insufficient space to pack PI_LATENCY data" ); + } + + buffer[nBytes++] = ( p->piDataType & MASK_5BIT ); + buffer[nBytes++] = 4; + + typeBits = (uint32_t) ( p->type & MASK_5BIT ); + latencyBits = (uint32_t) ( p->latency & 0x07FFFFFF ); + word = ( typeBits << 27 ) | latencyBits; + + buffer[nBytes++] = (uint8_t) ( word >> 24 ); + buffer[nBytes++] = (uint8_t) ( word >> 16 ); + buffer[nBytes++] = (uint8_t) ( word >> 8 ); + buffer[nBytes++] = (uint8_t) ( word ); + *nBytesWritten = nBytes; + + return IVAS_ERR_OK; +} + +static ivas_error unpackPiLatency( const uint8_t *buffer, uint32_t numDataBytes, IVAS_PIDATA_GENERIC *piData ) +{ + uint32_t word; + uint32_t lat; + IVAS_PIDATA_REVERSE_PI_LATENCY *p = (IVAS_PIDATA_REVERSE_PI_LATENCY *) piData; + + if ( numDataBytes != 4 ) + { + return IVAS_ERROR( IVAS_ERR_RTP_UNPACK_PI_DATA, "Incorrect size to unpack PI_LATENCY data" ); + } + + p->size = sizeof( IVAS_PIDATA_REVERSE_PI_LATENCY ); + p->piDataType = IVAS_PI_PI_LATENCY; + + word = ( (uint32_t) buffer[0] << 24 ) | ( (uint32_t) buffer[1] << 16 ) | + ( (uint32_t) buffer[2] << 8 ) | (uint32_t) buffer[3]; + p->type = (IVAS_PI_TYPE) ( ( word >> 27 ) & MASK_5BIT ); + lat = word & 0x07FFFFFF; + + /* Sign-extend 27-bit value */ + if ( lat & ( 1u << 26 ) ) + p->latency = (int32_t) ( lat | ~0x07FFFFFF ); + else + p->latency = (int32_t) lat; + + return IVAS_ERR_OK; +} +#endif +#ifdef ISM_PI_DATA +static ivas_error packISMGain( const IVAS_PIDATA_GENERIC *piData, uint8_t *buffer, uint32_t maxDataBytes, uint32_t *nBytesWritten ) +{ + uint32_t nBytes = 0, n, idx; + int16_t gain; + const IVAS_PIDATA_ISM_GAIN *ism_gain = (const IVAS_PIDATA_ISM_GAIN *) piData; + + *nBytesWritten = 0; + + if ( piData->size > sizeof( IVAS_PIDATA_ISM_GAIN ) ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect size in ISM_GAIN PI data" ); + } + + if ( piData->piDataType != IVAS_PI_ISM_GAIN ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect PI ID in ISM_GAIN PI data" ); + } + + /* ISM_GAIN data is 1 byte per object, header is 2 bytes */ + if ( maxDataBytes < 1 * IVAS_MAX_NUM_OBJECTS + 2 ) + { + return IVAS_ERROR( IVAS_ERR_RTP_INSUFFICIENT_OUTPUT_SIZE, "Insufficient space to pack ISM_GAIN PI data" ); + } + + buffer[nBytes++] = ( ism_gain->piDataType & MASK_5BIT ); /* PF/PM populated during final packing */ + buffer[nBytes++] = (uint8_t) ism_gain->numObjects; + /* Pack ID for each object */ + for ( n = 0; n < ism_gain->numObjects; n++ ) + { + gain = (int16_t) ism_gain->dB[n]; + idx = min( -gain, 25 ); + if ( gain > 0 ) + { + idx += 25; + } + + buffer[nBytes++] = ( idx & MASK_6BIT ) << 2; + } + *nBytesWritten = nBytes; + return IVAS_ERR_OK; +} + +static ivas_error unpackISMGain( const uint8_t *buffer, uint32_t numDataBytes, IVAS_PIDATA_GENERIC *piData ) +{ + uint32_t n, idx; + IVAS_PIDATA_ISM_GAIN *ism_gain = (IVAS_PIDATA_ISM_GAIN *) piData; + + /* ISM_GAIN data is 1 byte per object */ + if ( numDataBytes > IVAS_MAX_NUM_OBJECTS ) + { + return IVAS_ERROR( IVAS_ERR_RTP_UNPACK_PI_DATA, "Incorrect size to unpack ISM_GAIN PI data" ); + } + + ism_gain->size = sizeof( IVAS_PIDATA_ISM_GAIN ); + ism_gain->piDataType = IVAS_PI_ISM_GAIN; + ism_gain->numObjects = (uint16_t) numDataBytes; + + /* Unpack ID for each object (1 byte each) */ + for ( n = 0; n < ism_gain->numObjects; n++ ) + { + idx = ( buffer[n] ) >> 2; + /* negative gains*/ + if ( idx < 25 ) + { + ism_gain->dB[n] = -(int8_t) ( idx ); + } + /* Set to min for muting, to be interpreted as -Inf */ + else if ( idx == 25 ) + { + ism_gain->dB[n] = -128; + } + /* postive gains */ + else if ( idx < 38 ) + { + ism_gain->dB[n] = (int8_t) idx - 25; + } + else + { + return IVAS_ERROR( IVAS_ERR_RTP_UNPACK_PI_DATA, "Incorrect index for ISM_GAIN PI data" ); + } + } + for ( ; n < IVAS_MAX_NUM_OBJECTS; n++ ) + { + ism_gain->dB[n] = 0; /* Set to default */ + } + return IVAS_ERR_OK; +} + +static ivas_error packISMDistanceAttenuation( const IVAS_PIDATA_GENERIC *piData, uint8_t *buffer, uint32_t maxDataBytes, uint32_t *nBytesWritten ) +{ + uint32_t nBytes = 0, n; + const IVAS_PIDATA_ISM_ATTENUATION *ism_att = (const IVAS_PIDATA_ISM_ATTENUATION *) piData; + uint32_t lWord; + + *nBytesWritten = 0; + + if ( piData->size > sizeof( IVAS_PIDATA_ISM_ATTENUATION ) ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect size in ISM_DISTANCE_ATTENUATION PI data" ); + } + + if ( piData->piDataType != IVAS_PI_ISM_DISTANCE_ATTENUATION ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect PI ID in ISM_DISTANCE_ATTENUATION PI data" ); + } + + /* ISM_DISTANCE_ATTENUATION data is 3 bytes per object, header is 2 bytes */ + if ( maxDataBytes > 3 * IVAS_MAX_NUM_OBJECTS + 2 ) + { + return IVAS_ERROR( IVAS_ERR_RTP_INSUFFICIENT_OUTPUT_SIZE, "Insufficient space to pack ISM_DISTANCE_ATTENUATION PI data" ); + } + + buffer[nBytes++] = ( ism_att->piDataType & MASK_5BIT ); /* PF/PM populated during final packing */ + buffer[nBytes++] = (uint8_t) ism_att->numObjects * 3; + /* Pack ID for each object */ + for ( n = 0; n < ism_att->numObjects; n++ ) + { + if ( ism_att->distAtten[n].ref_dist < 0 || ism_att->distAtten[n].max_dist < 0 || ism_att->distAtten[n].roll < 0 ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect DISTANCE ATTENUATION data" ); + } + lWord = (uint32_t) ( min( (uint16_t) ( ism_att->distAtten[n].ref_dist * 10.0f + 0.5f ) - 1, 63 ) << 18 ); + lWord |= (uint32_t) ( min( (uint16_t) ( ism_att->distAtten[n].max_dist + 0.5f ) - 1, 63 ) << 12 ); + lWord |= (uint32_t) ( min( (uint16_t) ( ism_att->distAtten[n].roll * 10.0f + 0.5f ), 40 ) << 6 ); + + buffer[nBytes++] = ( lWord >> 16 ) & MASK_8BIT; + buffer[nBytes++] = ( lWord >> 8 ) & MASK_8BIT; + buffer[nBytes++] = lWord & MASK_8BIT; + } + *nBytesWritten = nBytes; + return IVAS_ERR_OK; +} + +static ivas_error unpackISMDistanceAttenuation( const uint8_t *buffer, uint32_t numDataBytes, IVAS_PIDATA_GENERIC *piData ) +{ + uint32_t n, lWord; + IVAS_PIDATA_ISM_ATTENUATION *ism_att = (IVAS_PIDATA_ISM_ATTENUATION *) piData; + + /* ISM_DISTANCE_ATTENUATION data is 3 bytes per object */ + if ( numDataBytes % 3 != 0 ) + { + return IVAS_ERROR( IVAS_ERR_RTP_UNPACK_PI_DATA, "Incorrect size to unpack ISM_DISTANCE_ATTENUATION PI data" ); + } + + ism_att->size = sizeof( IVAS_PIDATA_ISM_ATTENUATION ); + ism_att->piDataType = IVAS_PI_ISM_DISTANCE_ATTENUATION; + ism_att->numObjects = (uint16_t) numDataBytes / 3; + + /* Unpack attenuation for each object (3 bytes each) */ + for ( n = 0; n < ism_att->numObjects; n++ ) + { + lWord = ( buffer[3 * n] ) << 16; + lWord |= ( buffer[3 * n + 1] ) << 8; + lWord |= buffer[3 * n + 2]; + + ism_att->distAtten[n].ref_dist = ( ( ( lWord >> 18 ) & MASK_6BIT ) + 1 ) / 10.0f; + ism_att->distAtten[n].max_dist = (float) ( ( lWord >> 12 ) & MASK_6BIT ) + 1; + ism_att->distAtten[n].roll = ( ( lWord >> 6 ) & MASK_6BIT ) / 10.0f; + } + for ( ; n < IVAS_MAX_NUM_OBJECTS; n++ ) + { + ism_att->distAtten[n].ref_dist = 1.0f; /* Set to default */ + ism_att->distAtten[n].max_dist = 16.0f; /* Set to default */ + ism_att->distAtten[n].roll = 1.0f; /* Set to default */ + } + return IVAS_ERR_OK; +} +static ivas_error packISMDirectivity( const IVAS_PIDATA_GENERIC *piData, uint8_t *buffer, uint32_t maxDataBytes, uint32_t *nBytesWritten ) +{ + uint32_t nBytes = 0, n; + const IVAS_PIDATA_ISM_DIRECTIVITY *ism_directivity = (const IVAS_PIDATA_ISM_DIRECTIVITY *) piData; + uint16_t word, idx; + + *nBytesWritten = 0; + + if ( piData->size > sizeof( IVAS_PIDATA_ISM_DIRECTIVITY ) ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect size in ISM_DIRECTIVITY PI data" ); + } + + if ( piData->piDataType != IVAS_PI_ISM_DIRECTIVITY ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect PI ID in ISM_DIRECTIVITY PI data" ); + } + + /* ISM_DIRECTIVITY data is 2 bytes per object, header is 2 bytes */ + if ( maxDataBytes > 2 * IVAS_MAX_NUM_OBJECTS + 2 ) + { + return IVAS_ERROR( IVAS_ERR_RTP_INSUFFICIENT_OUTPUT_SIZE, "Insufficient space to pack ISM_DIRECTIVITY PI data" ); + } + + buffer[nBytes++] = ( ism_directivity->piDataType & MASK_5BIT ); /* PF/PM populated during final packing */ + buffer[nBytes++] = (uint8_t) ism_directivity->numObjects * 2; + /* Pack directivity for each object */ + for ( n = 0; n < ism_directivity->numObjects; n++ ) + { + word = (uint16_t) ( min( ism_directivity->directivity[n].innerConeAngle / 15, 24 ) << 11 ); + word |= (uint16_t) ( min( ism_directivity->directivity[n].outerConeAngle / 15, 24 ) << 6 ); + + idx = 0; + /* For outer attenuation < -90 dB, idx = 0, which corresponds to -Inf (muting) */ + if ( ism_directivity->directivity[n].outerAttenuationdB >= -90.0f ) + { + idx = 32 - (uint16_t) ( -ism_directivity->directivity[n].outerAttenuationdB / 3.0f + 0.5f ); + } + word |= (uint16_t) ( min( idx, 31 ) << 1 ); + + buffer[nBytes++] = ( word >> 8 ) & MASK_8BIT; + buffer[nBytes++] = word & MASK_8BIT; + } + *nBytesWritten = nBytes; + return IVAS_ERR_OK; +} + +static ivas_error unpackISMDirectivity( const uint8_t *buffer, uint32_t numDataBytes, IVAS_PIDATA_GENERIC *piData ) +{ + uint32_t n; + uint16_t word, idx; + IVAS_PIDATA_ISM_DIRECTIVITY *ism_directivity = (IVAS_PIDATA_ISM_DIRECTIVITY *) piData; + + /* ISM_DIRECTIVITY data is 2 bytes per object */ + if ( numDataBytes % 2 != 0 ) + { + return IVAS_ERROR( IVAS_ERR_RTP_UNPACK_PI_DATA, "Incorrect size to unpack ISM_DIRECTIVITY PI data" ); + } + + ism_directivity->size = sizeof( IVAS_PIDATA_ISM_DIRECTIVITY ); + ism_directivity->piDataType = IVAS_PI_ISM_DIRECTIVITY; + ism_directivity->numObjects = (uint16_t) numDataBytes / 2; + + /* Unpack directivity for each object (2 bytes each) */ + for ( n = 0; n < ism_directivity->numObjects; n++ ) + { + word = ( buffer[2 * n] ) << 8; + word |= ( buffer[2 * n + 1] ); + + ism_directivity->directivity[n].innerConeAngle = ( ( word >> 11 ) & MASK_5BIT ) * 15; + ism_directivity->directivity[n].outerConeAngle = ( ( word >> 6 ) & MASK_5BIT ) * 15; + idx = ( word >> 1 ) & MASK_5BIT; + + if ( idx == 0 ) + { + ism_directivity->directivity[n].outerAttenuationdB = -128.0f; /* corresponds to muting */ + } + else + { + ism_directivity->directivity[n].outerAttenuationdB = -3.0f * ( 31 - ( ( word >> 1 ) & MASK_5BIT ) ); + } + } + for ( ; n < IVAS_MAX_NUM_OBJECTS; n++ ) + { + ism_directivity->directivity[n].innerConeAngle = 360; /* Set to default */ + ism_directivity->directivity[n].outerConeAngle = 360; /* Set to default */ + ism_directivity->directivity[n].outerAttenuationdB = 0; /* Set to default */ + } + return IVAS_ERR_OK; +} +#endif + +#ifdef REVERSE_ISM_PI_DATA +static ivas_error packReverseISMID( const IVAS_PIDATA_GENERIC *piData, uint8_t *buffer, uint32_t maxDataBytes, uint32_t *nBytesWritten ) +{ + uint32_t nBytes = 0; + const IVAS_PIDATA_ISM_EDIT_ID *r_ism_id = (const IVAS_PIDATA_ISM_EDIT_ID *) piData; + + *nBytesWritten = 0; + + if ( piData->size > sizeof( IVAS_PIDATA_ISM_EDIT_ID ) ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect size in R_ISM_ID PI data" ); + } + + if ( piData->piDataType != IVAS_PI_R_ISM_ID ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect PI ID in R_ISM_ID PI data" ); + } + + /* R_ISM_ID data is 1 byte, header is 2 bytes */ + if ( maxDataBytes < 1 + 2 ) + { + return IVAS_ERROR( IVAS_ERR_RTP_INSUFFICIENT_OUTPUT_SIZE, "Insufficient space to pack R_ISM_NUM PI data" ); + } + + buffer[nBytes++] = ( r_ism_id->piDataType & MASK_5BIT ); /* PF/PM populated during final packing */ + buffer[nBytes++] = ( r_ism_id->id & MASK_8BIT ); + *nBytesWritten = nBytes; + return IVAS_ERR_OK; +} + +static ivas_error unpackReverseISMID( const uint8_t *buffer, uint32_t numDataBytes, IVAS_PIDATA_GENERIC *piData ) +{ + IVAS_PIDATA_ISM_EDIT_ID *r_ism_id = (IVAS_PIDATA_ISM_EDIT_ID *) piData; + + /* ISM_ID data is 1 byte*/ + if ( numDataBytes > 1 ) + { + return IVAS_ERROR( IVAS_ERR_RTP_UNPACK_PI_DATA, "Incorrect size to unpack R_ISM_ID PI data" ); + } + + r_ism_id->size = sizeof( IVAS_PIDATA_ISM_EDIT_ID ); + r_ism_id->piDataType = IVAS_PI_R_ISM_ID; + r_ism_id->id = *buffer; + + return IVAS_ERR_OK; +} + +static ivas_error packReverseISMGain( const IVAS_PIDATA_GENERIC *piData, uint8_t *buffer, uint32_t maxDataBytes, uint32_t *nBytesWritten ) +{ + uint32_t nBytes = 0, idx; + int16_t gain; + const IVAS_PIDATA_ISM_EDIT_GAIN *r_ism_gain = (const IVAS_PIDATA_ISM_EDIT_GAIN *) piData; + + *nBytesWritten = 0; + + if ( piData->size > sizeof( IVAS_PIDATA_ISM_EDIT_GAIN ) ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect size in R_ISM_GAIN PI data" ); + } + + if ( piData->piDataType != IVAS_PI_R_ISM_GAIN ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect PI ID in R_ISM_GAIN PI data" ); + } + + /* R_ISM_GAIN data is 1 byte, header is 2 bytes */ + if ( maxDataBytes < 1 + 2 ) + { + return IVAS_ERROR( IVAS_ERR_RTP_INSUFFICIENT_OUTPUT_SIZE, "Insufficient space to pack R_ISM_GAIN PI data" ); + } + + buffer[nBytes++] = ( r_ism_gain->piDataType & MASK_5BIT ); /* PF/PM populated during final packing */ + gain = (int16_t) r_ism_gain->dB; + idx = min( -gain, 25 ); + if ( gain > 0 ) + { + idx += 25; + } + + buffer[nBytes++] = ( idx & MASK_6BIT ) << 2; + *nBytesWritten = nBytes; + return IVAS_ERR_OK; +} + +static ivas_error unpackReverseISMGain( const uint8_t *buffer, uint32_t numDataBytes, IVAS_PIDATA_GENERIC *piData ) +{ + uint32_t idx; + IVAS_PIDATA_ISM_EDIT_GAIN *r_ism_gain = (IVAS_PIDATA_ISM_EDIT_GAIN *) piData; + + /* R_ISM_GAIN data is 1 byte */ + if ( numDataBytes > 1 ) + { + return IVAS_ERROR( IVAS_ERR_RTP_UNPACK_PI_DATA, "Incorrect size to unpack R_ISM_GAIN PI data" ); + } + + r_ism_gain->size = sizeof( IVAS_PIDATA_ISM_EDIT_GAIN ); + r_ism_gain->piDataType = IVAS_PI_R_ISM_GAIN; + + /* Unpack gain */ + idx = ( *buffer ) >> 2; + /* negative gains*/ + if ( idx < 25 ) + { + r_ism_gain->dB = -(int8_t) ( idx ); + } + /* Set to min for muting, to be interpreted as -Inf */ + else if ( idx == 25 ) + { + r_ism_gain->dB = -128; + } + /* postive gains */ + else if ( idx < 38 ) + { + r_ism_gain->dB = (int8_t) idx - 25; + } + else + { + return IVAS_ERROR( IVAS_ERR_RTP_UNPACK_PI_DATA, "Incorrect index for R_ISM_GAIN PI data" ); + } + + return IVAS_ERR_OK; +} + +static ivas_error packReverseISMDirection( const IVAS_PIDATA_GENERIC *piData, uint8_t *buffer, uint32_t maxDataBytes, uint32_t *nBytesWritten ) +{ + uint32_t nBytes = 0; + const IVAS_PIDATA_ISM_EDIT_DIRECTION *r_ism_direction = (const IVAS_PIDATA_ISM_EDIT_DIRECTION *) piData; + uint16_t word; + + *nBytesWritten = 0; + + if ( piData->size > sizeof( IVAS_PIDATA_ISM_EDIT_DIRECTION ) ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect size in R_ISM_DIRECTION PI data" ); + } + + if ( piData->piDataType != IVAS_PI_R_ISM_DIRECTION ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect PI ID in ISM_DIRECTION PI data" ); + } + + /* R_ISM_DIRECTION data is 2 bytes, header is 2 bytes */ + if ( maxDataBytes > 2 + 2 ) + { + return IVAS_ERROR( IVAS_ERR_RTP_INSUFFICIENT_OUTPUT_SIZE, "Insufficient space to pack R_ISM_DIRECTION PI data" ); + } + + buffer[nBytes++] = ( r_ism_direction->piDataType & MASK_5BIT ); /* PF/PM populated during final packing */ + + word = (uint16_t) ( min( (uint16_t) ceilf( r_ism_direction->azimuth * REVERSE_ISM_DIRECTION_AZIMUTH_STEP_INV ) + 256, 511 ) << 7 ); + word |= (uint16_t) ( min( (uint16_t) ceilf( r_ism_direction->elevation * REVERSE_ISM_DIRECTION_ELEVATION_STEP_INV ) + 64, 127 ) << 6 ); + + buffer[nBytes++] = ( word >> 8 ) & MASK_8BIT; + buffer[nBytes++] = word & MASK_8BIT; + + *nBytesWritten = nBytes; + return IVAS_ERR_OK; +} + +static ivas_error unpackReverseISMDirection( const uint8_t *buffer, uint32_t numDataBytes, IVAS_PIDATA_GENERIC *piData ) +{ + uint16_t word; + IVAS_PIDATA_ISM_EDIT_DIRECTION *r_ism_direction = (IVAS_PIDATA_ISM_EDIT_DIRECTION *) piData; + + /* R_ISM_DIRECTION data is 2 bytes */ + if ( numDataBytes > 2 ) + { + return IVAS_ERROR( IVAS_ERR_RTP_UNPACK_PI_DATA, "Incorrect size to unpack R_ISM_DIRECTION PI data" ); + } + + r_ism_direction->size = sizeof( IVAS_PIDATA_ISM_EDIT_DIRECTION ); + r_ism_direction->piDataType = IVAS_PI_R_ISM_DIRECTION; + + word = ( buffer[0] ) << 8; + word |= ( buffer[1] ); + + r_ism_direction->azimuth = (float) ( ( ( word >> 7 ) & MASK_9BIT ) + 1 ) * REVERSE_ISM_DIRECTION_AZIMUTH_STEP - 180.0f; + r_ism_direction->elevation = (float) ( word & MASK_7BIT ) * REVERSE_ISM_DIRECTION_ELEVATION_STEP - 90.0f; + + return IVAS_ERR_OK; +} +#endif #endif /* RTP_S4_251135_CR26253_0016_REV1 */ @@ -642,14 +1460,24 @@ static const PACK_PI_FN packPiDataFuntions[IVAS_PI_MAX_ID] = { packAudioDescription, /* AUDIO_DESCRIPTION */ #else packUnsupportedData, /* AUDIO_DESCRIPTION */ -#endif /* RTP_S4_251135_CR26253_0016_REV1 */ - packUnsupportedData, /* ISM_NUM */ - packUnsupportedData, /* ISM_ID */ - packUnsupportedData, /* ISM_GAIN */ - packUnsupportedData, /* ISM_ORIENTATION */ - packUnsupportedData, /* ISM_POSITION */ - packUnsupportedData, /* ISM_DISTANCE_ATTENUATION */ - packUnsupportedData, /* ISM_DIRECTIVITY */ +#endif /* RTP_S4_251135_CR26253_0016_REV1 */ +#ifdef ISM_PI_DATA + packISMNum, /* ISM_NUM */ + packISMID, /* ISM_ID */ + packISMGain, /* ISM_GAIN */ + packISMOrientation, /* ISM_ORIENTATION */ + packISMPosition, /* ISM_POSITION */ + packISMDistanceAttenuation, /* ISM_DISTANCE_ATTENUATION */ + packISMDirectivity, /* ISM_DIRECTIVITY */ +#else + packUnsupportedData, /* ISM_NUM */ + packUnsupportedData, /* ISM_ID */ + packUnsupportedData, /* ISM_GAIN */ + packUnsupportedData, /* ISM_ORIENTATION */ + packUnsupportedData, /* ISM_POSITION */ + packUnsupportedData, /* ISM_DISTANCE_ATTENUATION */ + packUnsupportedData, /* ISM_DIRECTIVITY */ +#endif #ifdef RTP_S4_251135_CR26253_0016_REV1 packDiegetic, /* DIEGETIC_TYPE */ #else @@ -663,28 +1491,47 @@ static const PACK_PI_FN packPiDataFuntions[IVAS_PI_MAX_ID] = { #endif packUnsupportedData, /* RESERVED15 */ #ifdef RTP_S4_251135_CR26253_0016_REV1 - packOrientation, /* PLAYBACK_DEVICE_ORIENTATION */ - packOrientation, /* HEAD_ORIENTATION */ + packOrientation, /* PLAYBACK_DEVICE_ORIENTATION */ + packOrientation, /* HEAD_ORIENTATION */ +#ifdef REVERSE_ISM_PI_DATA + packPosition, /* LISTENER_POSITION */ +#else packListenerPosition, /* LISTENER_POSITION */ +#endif packDynamicSuppression, /* DYNAMIC_AUDIO_SUPPRESSION */ packAudioFocusCommon, /* AUDIO_FOCUS_REQUEST */ +#ifdef PI_LATENCY + packPiLatency, /* PI_LATENCY */ +#else + packUnsupportedData, /* PI_LATENCY */ +#endif #else packUnsupportedData, /* PLAYBACK_DEVICE_ORIENTATION */ packUnsupportedData, /* HEAD_ORIENTATION */ packUnsupportedData, /* LISTENER_POSITION */ packUnsupportedData, /* DYNAMIC_AUDIO_SUPPRESSION */ packUnsupportedData, /* AUDIO_FOCUS_DIRECTION */ + packUnsupportedData, /* PI_LATENCY */ +#endif +#ifdef REVERSE_ISM_PI_DATA + packReverseISMID, /* R_ISM_ID */ + packReverseISMGain, /* R_ISM_GAIN */ +#else + packUnsupportedData, /* R_ISM_ID */ + packUnsupportedData, /* R_ISM_GAIN */ #endif - packUnsupportedData, /* PI_LATENCY */ - packUnsupportedData, /* R_ISM_ID */ - packUnsupportedData, /* R_ISM_GAIN */ #ifdef RTP_S4_251135_CR26253_0016_REV1 packOrientation, /* R_ISM_ORIENTATION */ #else packUnsupportedData, /* R_ISM_ORIENTATION */ #endif - packUnsupportedData, /* R_ISM_POSITION */ - packUnsupportedData, /* R_ISM_DIRECTION */ +#ifdef REVERSE_ISM_PI_DATA + packPosition, /* R_ISM_POSITION */ + packReverseISMDirection, /* R_ISM_DIRECTION */ +#else + packUnsupportedData, /* R_ISM_POSITION */ + packUnsupportedData, /* R_ISM_DIRECTION */ +#endif packUnsupportedData, /* RESERVED27 */ packUnsupportedData, /* RESERVED28 */ packUnsupportedData, /* RESERVED29 */ @@ -702,6 +1549,15 @@ static const UNPACK_PI_FN unpackPiDataFuntions[IVAS_PI_MAX_ID] = { #else unpackUnsupportedData, /* AUDIO_DESCRIPTION */ #endif +#ifdef ISM_PI_DATA + unpackISMNum, /* ISM_NUM */ + unpackISMID, /* ISM_ID */ + unpackISMGain, /* ISM_GAIN */ + unpackISMOrientation, /* ISM_ORIENTATION */ + unpackISMPosition, /* ISM_POSITION */ + unpackISMDistanceAttenuation, /* ISM_DISTANCE_ATTENUATION */ + unpackISMDirectivity, /* ISM_DIRECTIVITY */ +#else unpackUnsupportedData, /* ISM_NUM */ unpackUnsupportedData, /* ISM_ID */ unpackUnsupportedData, /* ISM_GAIN */ @@ -709,6 +1565,7 @@ static const UNPACK_PI_FN unpackPiDataFuntions[IVAS_PI_MAX_ID] = { unpackUnsupportedData, /* ISM_POSITION */ unpackUnsupportedData, /* ISM_DISTANCE_ATTENUATION */ unpackUnsupportedData, /* ISM_DIRECTIVITY */ +#endif #ifdef RTP_S4_251135_CR26253_0016_REV1 unpackDiegetic, /* DIEGETIC_TYPE */ #else @@ -722,28 +1579,47 @@ static const UNPACK_PI_FN unpackPiDataFuntions[IVAS_PI_MAX_ID] = { #endif unpackUnsupportedData, /* RESERVED15 */ #ifdef RTP_S4_251135_CR26253_0016_REV1 - unpackOrientation, /* PLAYBACK_DEVICE_ORIENTATION */ - unpackOrientation, /* HEAD_ORIENTATION */ - unpackListenerPosition, /* LISTENER_POSITION */ + unpackOrientation, /* PLAYBACK_DEVICE_ORIENTATION */ + unpackOrientation, /* HEAD_ORIENTATION */ +#ifdef REVERSE_ISM_PI_DATA + unpackPosition, /* LISTENER_POSITION */ +#else + unpackListenerPosition, /* LISTENER_POSITION */ +#endif unpackDynamicSuppression, /* DYNAMIC_AUDIO_SUPPRESSION */ unpackAudioFocusCommon, /* AUDIO_FOCUS_REQUEST */ +#ifdef PI_LATENCY + unpackPiLatency, /* PI_LATENCY */ +#else + unpackUnsupportedData, /* PI_LATENCY */ +#endif #else unpackUnsupportedData, /* PLAYBACK_DEVICE_ORIENTATION */ unpackUnsupportedData, /* HEAD_ORIENTATION */ unpackUnsupportedData, /* LISTENER_POSITION */ unpackUnsupportedData, /* DYNAMIC_AUDIO_SUPPRESSION */ + unpackUnsupportedData, /* PI_LATENCY */ unpackUnsupportedData, /* AUDIO_FOCUS_DIRECTION */ #endif - unpackUnsupportedData, /* PI_LATENCY */ +#ifdef REVERSE_ISM_PI_DATA + unpackReverseISMID, /* R_ISM_ID */ + unpackReverseISMGain, /* R_ISM_GAIN */ +#else unpackUnsupportedData, /* R_ISM_ID */ unpackUnsupportedData, /* R_ISM_GAIN */ +#endif #ifdef RTP_S4_251135_CR26253_0016_REV1 unpackOrientation, /* R_ISM_ORIENTATION */ #else unpackUnsupportedData, /* R_ISM_ORIENTATION */ #endif +#ifdef REVERSE_ISM_PI_DATA + unpackPosition, /* R_ISM_POSITION */ + unpackReverseISMDirection, /* R_ISM_DIRECTION */ +#else unpackUnsupportedData, /* R_ISM_POSITION */ unpackUnsupportedData, /* R_ISM_DIRECTION */ +#endif unpackUnsupportedData, /* RESERVED27 */ unpackUnsupportedData, /* RESERVED28 */ unpackUnsupportedData, /* RESERVED29 */ @@ -845,5 +1721,4 @@ const float mapAbsorbtion[1u << NBITS_ABS] = { 0.0800f, 0.1656f, 0.3430f, 0.7101f }; - #endif /* IVAS_RTPDUMP */ diff --git a/lib_util/ivas_rtp_pi_data.h b/lib_util/ivas_rtp_pi_data.h index dc4c7f8bafd5eda274df74b419677fd28ec1c64a..95a2ac99429f7ba825e594eee4bf56d1dfdb1309 100644 --- a/lib_util/ivas_rtp_pi_data.h +++ b/lib_util/ivas_rtp_pi_data.h @@ -39,6 +39,13 @@ #define IVAS_PI_MAX_DATA_SIZE ( 32 + 2 ) /* max packed PI data bytes + pi header bytes */ +#ifdef REVERSE_ISM_PI_DATA +#define REVERSE_ISM_DIRECTION_AZIMUTH_STEP 0.703125f +#define REVERSE_ISM_DIRECTION_ELEVATION_STEP 1.417322835f +#define REVERSE_ISM_DIRECTION_AZIMUTH_STEP_INV 1.4222222222f +#define REVERSE_ISM_DIRECTION_ELEVATION_STEP_INV 0.7055555556f +#endif + /* IVAS PI Data Types */ typedef enum { @@ -124,6 +131,15 @@ typedef enum IVAS_PI_AE_NUM_BANDS /* number of ae bands */ } IVAS_PI_AE_BANDS; +#ifdef IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT +typedef enum +{ + IVAS_PI_AE_LOW_FREQ = 25, + IVAS_PI_AE_MID_FREQ = 250, + IVAS_PI_AE_HIGH_FREQ = 2500 +} IVAS_PI_AE_BANDS_FREQ; +#endif + typedef enum { IVAS_PI_AE_FRONT, @@ -205,32 +221,44 @@ typedef struct /* ISM ID */ typedef struct { - size_t size; /* sizeof(IVAS_PIDATA_ISM_ID) */ - uint32_t piDataType; /* IVAS_PI_ISM_ID */ + size_t size; /* sizeof(IVAS_PIDATA_ISM_ID) */ + uint32_t piDataType; /* IVAS_PI_ISM_ID */ +#ifdef ISM_PI_DATA + uint16_t numObjects; /* number of objects */ +#endif uint8_t id[IVAS_MAX_NUM_OBJECTS]; /* 8-bit ISM id of object */ } IVAS_PIDATA_ISM_ID; /* ISM gain */ typedef struct { - size_t size; /* sizeof(IVAS_PIDATA_ISM_GAIN) */ - uint32_t piDataType; /* IVAS_PI_ISM_GAIN */ + size_t size; /* sizeof(IVAS_PIDATA_ISM_GAIN) */ + uint32_t piDataType; /* IVAS_PI_ISM_GAIN */ +#ifdef ISM_PI_DATA + uint16_t numObjects; /* number of objects */ +#endif int8_t dB[IVAS_MAX_NUM_OBJECTS]; /* ISM gain in dB per object [-96, +3] */ } IVAS_PIDATA_ISM_GAIN; /* ISM orientation */ typedef struct { - size_t size; /* sizeof(IVAS_PIDATA_ISM_ORIENTATION) */ - uint32_t piDataType; /* IVAS_PI_ISM_ORIENTATION */ + size_t size; /* sizeof(IVAS_PIDATA_ISM_ORIENTATION) */ + uint32_t piDataType; /* IVAS_PI_ISM_ORIENTATION */ +#ifdef ISM_PI_DATA + uint16_t numObjects; /* number of objects */ +#endif IVAS_QUATERNION orientation[IVAS_MAX_NUM_OBJECTS]; /* Orientation of audio objects in ISM(s) */ } IVAS_PIDATA_ISM_ORIENTATION; /* ISM position */ typedef struct { - size_t size; /* sizeof(IVAS_PIDATA_ISM_POSITION) */ - uint32_t piDataType; /* IVAS_PI_ISM_POSITION */ + size_t size; /* sizeof(IVAS_PIDATA_ISM_POSITION) */ + uint32_t piDataType; /* IVAS_PI_ISM_POSITION */ +#ifdef ISM_PI_DATA + uint16_t numObjects; /* number of objects */ +#endif IVAS_COORDINATE position[IVAS_MAX_NUM_OBJECTS]; /* Position of audio objects in ISM(s) */ } IVAS_PIDATA_ISM_POSITION; @@ -248,8 +276,11 @@ typedef struct typedef struct { - size_t size; /* sizeof(IVAS_PIDATA_ISM_ATTENUATION) */ - uint32_t piDataType; /* IVAS_PI_ISM_DISTANCE_ATTENUATION */ + size_t size; /* sizeof(IVAS_PIDATA_ISM_ATTENUATION) */ + uint32_t piDataType; /* IVAS_PI_ISM_DISTANCE_ATTENUATION */ +#ifdef ISM_PI_DATA + uint16_t numObjects; /* number of objects */ +#endif IVAS_DIST_ATTEN distAtten[IVAS_MAX_NUM_OBJECTS]; /* Distance attenuation of audio objects */ } IVAS_PIDATA_ISM_ATTENUATION; @@ -267,8 +298,11 @@ typedef struct typedef struct { - size_t size; /* sizeof(IVAS_PIDATA_ISM_DIRECTIVITY) */ - uint32_t piDataType; /* IVAS_PI_ISM_DIRECTIVITY */ + size_t size; /* sizeof(IVAS_PIDATA_ISM_DIRECTIVITY) */ + uint32_t piDataType; /* IVAS_PI_ISM_DIRECTIVITY */ +#ifdef ISM_PI_DATA + uint16_t numObjects; /* number of objects */ +#endif IVAS_ISM_DIRECTIVITY directivity[IVAS_MAX_NUM_OBJECTS]; /* Directivity of audio objects */ } IVAS_PIDATA_ISM_DIRECTIVITY; @@ -320,6 +354,20 @@ typedef struct IVAS_FLVL flvl; /* audio focus level */ } IVAS_PIDATA_AUDIO_FOCUS; +#ifdef REVERSE_ISM_PI_DATA +/* Position data corresponding to any of the following pi data types :- + * - IVAS_PI_LISTENER_POSITION + * - IVAS_PI_R_ISM_POSITION + * + * piDataType is used to identify the correct pi data type contained here + */ +typedef struct +{ + size_t size; /* sizeof(IVAS_PIDATA_POSITION) */ + uint32_t piDataType; /* one of supported position data types */ + IVAS_COORDINATE position; /* Position data */ +} IVAS_PIDATA_POSITION; +#else /* Listener position */ typedef struct { @@ -327,7 +375,7 @@ typedef struct uint32_t piDataType; /* IVAS_PI_LISTENER_POSITION */ IVAS_COORDINATE position; /* Position of audio objects in ISM(s) */ } IVAS_PIDATA_LISTENER_POSITION; - +#endif /* Dynamic Audio Suppression describes receiver’s preference with respect to the * type of audio content that should be enhanced and the amount of suppression to @@ -402,6 +450,7 @@ typedef struct IVAS_QUATERNION orientation; /* orientation editing request for received ISM */ } IVAS_PIDATA_ISM_EDIT_ORIENTATION; +#ifndef REVERSE_ISM_PI_DATA /* Editing request for ISM position */ typedef struct { @@ -409,6 +458,7 @@ typedef struct uint32_t piDataType; /* IVAS_PI_R_ISM_POSITION */ IVAS_COORDINATE position; /* Positional editing request for received ISM */ } IVAS_PIDATA_ISM_EDIT_POSITION; +#endif /* Editing request for ISM direction */ typedef struct @@ -448,20 +498,28 @@ typedef union IVAS_PIDATA_ORIENTATION playbackOrientation; IVAS_PIDATA_ORIENTATION headOrientation; +#ifdef REVERSE_ISM_PI_DATA + IVAS_PIDATA_POSITION listnerPosition; +#else IVAS_PIDATA_LISTENER_POSITION listnerPosition; +#endif IVAS_PIDATA_DYNAMIC_SUPPRESSION dynSuppressionRequest; IVAS_PIDATA_AUDIO_FOCUS focusRequest; IVAS_PIDATA_REVERSE_PI_LATENCY piLatency; IVAS_PIDATA_ISM_EDIT_ID ismEditId; IVAS_PIDATA_ISM_EDIT_GAIN ismEditGain; IVAS_PIDATA_ISM_EDIT_ORIENTATION ismEditOrientation; +#ifdef REVERSE_ISM_PI_DATA + IVAS_PIDATA_POSITION ismEditPosition; +#else IVAS_PIDATA_ISM_EDIT_POSITION ismEditPosition; +#endif IVAS_PIDATA_ISM_EDIT_DIRECTION ismEditDirection; #endif /* RTP_S4_251135_CR26253_0016_REV1 */ IVAS_PIDATA_NO_DATA noPiData; } PIDATA; -typedef struct +typedef struct pidata_ts_struct { PIDATA data; uint32_t timestamp; diff --git a/lib_util/obj_edit_file_reader.c b/lib_util/obj_edit_file_reader.c index 2dde08ecc3936931f11956757739ede7521439a9..f4140ad3c51796bbb7ebbc16210cefde47d31d7a 100644 --- a/lib_util/obj_edit_file_reader.c +++ b/lib_util/obj_edit_file_reader.c @@ -77,8 +77,11 @@ ivas_error ObjectEditFileReader_open( } self = (ObjectEditFileReader *) calloc( 1, sizeof( ObjectEditFileReader ) ); - +#ifndef FIX_1427_OBJ_EDITING_EXT_METADATA self->maxLineLen = 256; +#else + self->maxLineLen = 1024; +#endif self->editFileHandle = fileHandle; self->inLine = (char *) calloc( self->maxLineLen, sizeof( char ) ); @@ -97,6 +100,17 @@ ivas_error ObjectEditFileReader_open( self->readInfo->obj_ele[obj_idx] = 0.0f; self->readInfo->obj_ele_edited[obj_idx] = false; self->readInfo->obj_ele_relative[obj_idx] = false; +#ifdef FIX_1427_OBJ_EDITING_EXT_METADATA + self->readInfo->obj_radius[obj_idx] = 0.0f; + self->readInfo->obj_radius_edited[obj_idx] = false; + self->readInfo->obj_radius_relative[obj_idx] = false; + self->readInfo->obj_yaw[obj_idx] = 0.0f; + self->readInfo->obj_yaw_edited[obj_idx] = false; + self->readInfo->obj_yaw_relative[obj_idx] = false; + self->readInfo->obj_pitch[obj_idx] = 0.0f; + self->readInfo->obj_pitch_edited[obj_idx] = false; + self->readInfo->obj_pitch_relative[obj_idx] = false; +#endif } self->rewound = false; @@ -143,6 +157,14 @@ ivas_error ObjectEditFileReader_readNextFrame( readEdits->obj_azi_relative[obj_idx] = false; readEdits->obj_ele_edited[obj_idx] = false; readEdits->obj_ele_relative[obj_idx] = false; +#ifdef FIX_1427_OBJ_EDITING_EXT_METADATA + readEdits->obj_radius_edited[obj_idx] = false; + readEdits->obj_radius_relative[obj_idx] = false; + readEdits->obj_yaw_edited[obj_idx] = false; + readEdits->obj_yaw_relative[obj_idx] = false; + readEdits->obj_pitch_edited[obj_idx] = false; + readEdits->obj_pitch_relative[obj_idx] = false; +#endif } /* tokenize the line by comma */ @@ -214,6 +236,35 @@ ivas_error ObjectEditFileReader_readNextFrame( { readEdits->obj_ele_relative[obj_idx] = ( strcmp( paramValue, "1" ) == 0 ); } +#ifdef FIX_1427_OBJ_EDITING_EXT_METADATA + else if ( strcmp( param, "radius" ) == 0 ) + { + readEdits->obj_radius[obj_idx] = strtof( paramValue, NULL ); + readEdits->obj_radius_edited[obj_idx] = true; + } + else if ( strcmp( param, "yaw" ) == 0 ) + { + readEdits->obj_yaw[obj_idx] = strtof( paramValue, NULL ); + readEdits->obj_yaw_edited[obj_idx] = true; + } + else if ( strcmp( param, "pitch" ) == 0 ) + { + readEdits->obj_pitch[obj_idx] = strtof( paramValue, NULL ); + readEdits->obj_pitch_edited[obj_idx] = true; + } + else if ( strcmp( param, "relradius" ) == 0 ) + { + readEdits->obj_radius_relative[obj_idx] = ( strcmp( paramValue, "1" ) == 0 ); + } + else if ( strcmp( param, "relyaw" ) == 0 ) + { + readEdits->obj_yaw_relative[obj_idx] = ( strcmp( paramValue, "1" ) == 0 ); + } + else if ( strcmp( param, "relpitch" ) == 0 ) + { + readEdits->obj_pitch_relative[obj_idx] = ( strcmp( paramValue, "1" ) == 0 ); + } +#endif } } } @@ -237,6 +288,20 @@ ivas_error ObjectEditFileReader_readNextFrame( { readEdits->obj_ele[obj_idx] = max( min( readEdits->obj_ele[obj_idx], 90.f ), -90.f ); } +#ifdef FIX_1427_OBJ_EDITING_EXT_METADATA + if ( readEdits->obj_radius_edited[obj_idx] && !readEdits->obj_radius_relative[obj_idx] ) + { + readEdits->obj_radius[obj_idx] = max( min( readEdits->obj_radius[obj_idx], OBJ_EDIT_RADIUS_MAX ), 0.0f ); + } + if ( readEdits->obj_yaw_edited[obj_idx] && !readEdits->obj_yaw_relative[obj_idx] ) + { + readEdits->obj_yaw[obj_idx] = max( min( readEdits->obj_yaw[obj_idx], 180.f ), -180.f ); + } + if ( readEdits->obj_pitch_edited[obj_idx] && !readEdits->obj_pitch_relative[obj_idx] ) + { + readEdits->obj_pitch[obj_idx] = max( min( readEdits->obj_pitch[obj_idx], 90.f ), -90.f ); + } +#endif } } else diff --git a/lib_util/obj_edit_file_reader.h b/lib_util/obj_edit_file_reader.h index 06b92a74d2d4a716e7e1c1f7b4eb7f33145ac53f..5f6864281faeb5af5e4c0088a52b9b6a70a05478 100644 --- a/lib_util/obj_edit_file_reader.h +++ b/lib_util/obj_edit_file_reader.h @@ -40,9 +40,17 @@ the United Nations Convention on Contracts on the International Sales of Goods. /*---------------------------------------------------------------------* * Constants ans structures *---------------------------------------------------------------------*/ - +#ifdef FIX_GAIN_EDIT_LIMITS +#define OBJ_EDIT_GAIN_MIN 0.0f /* -inf dB */ +#define OBJ_EDIT_GAIN_MAX 3.9810719f /* +12 dB */ +#else #define OBJ_EDIT_GAIN_MIN 0.06309573f /* -24 dB */ #define OBJ_EDIT_GAIN_MAX 15.84893f /* +24 dB */ +#endif + +#ifdef FIX_1427_OBJ_EDITING_EXT_METADATA +#define OBJ_EDIT_RADIUS_MAX 15.75f /* Max radius = (2^ISM_RADIUS_NBITS-1)*0.25 = 15.75 */ +#endif typedef struct ObjectEditFileReader ObjectEditFileReader; typedef struct ReadObjectEditInfo ReadObjectEditInfo; @@ -63,6 +71,20 @@ struct ReadObjectEditInfo float obj_ele[IVAS_MAX_NUM_OBJECTS]; bool obj_ele_edited[IVAS_MAX_NUM_OBJECTS]; bool obj_ele_relative[IVAS_MAX_NUM_OBJECTS]; + +#ifdef FIX_1427_OBJ_EDITING_EXT_METADATA + float obj_radius[IVAS_MAX_NUM_OBJECTS]; + bool obj_radius_edited[IVAS_MAX_NUM_OBJECTS]; + bool obj_radius_relative[IVAS_MAX_NUM_OBJECTS]; + + float obj_yaw[IVAS_MAX_NUM_OBJECTS]; + bool obj_yaw_edited[IVAS_MAX_NUM_OBJECTS]; + bool obj_yaw_relative[IVAS_MAX_NUM_OBJECTS]; + + float obj_pitch[IVAS_MAX_NUM_OBJECTS]; + bool obj_pitch_edited[IVAS_MAX_NUM_OBJECTS]; + bool obj_pitch_relative[IVAS_MAX_NUM_OBJECTS]; +#endif }; struct ObjectEditFileReader diff --git a/lib_util/render_config_reader.c b/lib_util/render_config_reader.c index 7729efbc7cb0ffe9ca4174f7aa12ea7012c5a67c..761b203cb09e1b2fb3a1be65906a86a7c85bc100 100644 --- a/lib_util/render_config_reader.c +++ b/lib_util/render_config_reader.c @@ -36,7 +36,9 @@ #include #include #include "cmdl_tools.h" - +#ifdef IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT +#include "ivas_cnst.h" +#endif /*------------------------------------------------------------------------------------------* * PreProc Local Macros @@ -2957,8 +2959,90 @@ ivas_error RenderConfigReader_read( return IVAS_ERR_OK; } +#ifdef IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT +/*------------------------------------------------------------------------------------------* + * RenderConfigReader_getAcousticEnvironmentCount() + * + * Gets number of acoustic environments available + *------------------------------------------------------------------------------------------*/ +uint32_t RenderConfigReader_getAcousticEnvironmentCount( + RenderConfigReader *pRenderConfigReader /* i : RenderConfigReader handle */ +) +{ + return pRenderConfigReader->nAE; +} + +/*------------------------------------------------------------------------------------------* + * RenderConfigReader_getAcousticEnvironments() + * + * Gets all acoustic environments + *------------------------------------------------------------------------------------------*/ +ivas_error RenderConfigReader_getAcousticEnvironments( + RenderConfigReader *pRenderConfigReader, /* i : RenderConfigReader handle */ + IVAS_ROOM_ACOUSTICS_CONFIG_DATA **ppAcEnv /* o : Acoustic environment array pointer */ +) +{ + uint16_t n, m, j; + + if ( pRenderConfigReader == NULL || ppAcEnv == NULL || pRenderConfigReader->nAE == 0 || pRenderConfigReader->pAE == NULL ) + { + return 0; + } + + for ( n = 0; n < pRenderConfigReader->nAE; n++ ) + { + AcousticEnv pIn = pRenderConfigReader->pAE[n]; + IVAS_ROOM_ACOUSTICS_CONFIG_DATA *pOut = ppAcEnv[n]; + + pOut->aeID = (uint16_t) pIn.id; + pOut->nBands = (uint16_t) pIn.pFG->nrBands; + pOut->inputPreDelay = pIn.preDelay; + + for ( m = 0; m < pOut->nBands; m++ ) + { + pOut->pFc_input[m] = pIn.pFG->pFc[m]; + pOut->pAcoustic_rt60[m] = pIn.pRT60[m]; + pOut->pAcoustic_dsr[m] = pIn.pDSR[m]; + } + + /* If ER are allocated then propagate parameters */ + if ( pIn.pEarlyReflections != 0 ) + { + pOut->use_er = pIn.pEarlyReflections->use_er; /* ER activation flag */ + pOut->lowComplexity = pIn.pEarlyReflections->lowComplexity; /* Low complexity flag */ + pOut->dimensions = pIn.pEarlyReflections->dimensions; + + /* Use default listener origin position if non provided */ + if ( pIn.pEarlyReflections->pListenerOrigin != NULL ) + { + pOut->ListenerOrigin.x = pIn.pEarlyReflections->pListenerOrigin->x; + pOut->ListenerOrigin.y = pIn.pEarlyReflections->pListenerOrigin->y; + pOut->ListenerOrigin.z = pIn.pEarlyReflections->pListenerOrigin->z; + } + else + { + pOut->ListenerOrigin.x = IVAS_ER_LIST_ORIGIN_X; + pOut->ListenerOrigin.y = IVAS_ER_LIST_ORIGIN_Y; + pOut->ListenerOrigin.z = IVAS_ER_LIST_HEIGHT; + } + + for ( j = 0; j < IVAS_ROOM_ABS_COEFF; j++ ) + { + pOut->AbsCoeff[j] = pIn.pEarlyReflections->pAbsCoeff[j]; + } + } + else + { + pOut->use_er = false; + } + } + + return IVAS_ERR_OK; +} +#endif + /*------------------------------------------------------------------------------------------* - * RenderConfigReader_getEnvironment() + * RenderConfigReader_getAcousticEnvironment() * * Gets Acoustic environment with a given ID *------------------------------------------------------------------------------------------*/ @@ -2978,7 +3062,11 @@ ivas_error RenderConfigReader_getAcousticEnvironment( } /* case when -aeid is not specified, select first ID from config file */ +#ifdef IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT + if ( id == IVAS_DEFAULT_AEID && pRenderConfigReader->nAE > 0 ) +#else if ( id == 65535 && pRenderConfigReader->nAE > 0 ) +#endif { id = (uint16_t) pRenderConfigReader->pAE[0].id; } diff --git a/lib_util/render_config_reader.h b/lib_util/render_config_reader.h index 8edaecc2f4b6b1c6290010e0f8b2a23fb63ab141..d69249734fa01d8af45162f633ccb786caec8962 100644 --- a/lib_util/render_config_reader.h +++ b/lib_util/render_config_reader.h @@ -51,12 +51,26 @@ ivas_error RenderConfigReader_open( RenderConfigReader **ppRenderConfigReader /* o : RenderConfigReader handle */ ); +#ifdef IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT +/* Get number of acoustic environments */ +uint32_t RenderConfigReader_getAcousticEnvironmentCount( + RenderConfigReader *pRenderConfigReader /* i : RenderConfigReader handle */ +); + +/* Get all acoustic environments */ +ivas_error RenderConfigReader_getAcousticEnvironments( + RenderConfigReader *pRenderConfigReader, /* i : RenderConfigReader handle */ + IVAS_ROOM_ACOUSTICS_CONFIG_DATA **ppAcEnv /* o : Acoustic environment array pointer */ +); +#endif + /* Get an acoustic environment */ ivas_error RenderConfigReader_getAcousticEnvironment( RenderConfigReader *pRenderConfigReader, /* i : RenderConfigReader handle */ uint16_t id, /* i : Acoustic environment ID */ IVAS_ROOM_ACOUSTICS_CONFIG_DATA *pAcEnv /* o : Target acoustic environment pointer */ ); + ivas_error RenderConfigReader_getDirectivity( RenderConfigReader *pRenderConfigReader, /* i : RenderConfigReader handle */ uint16_t *pId, /* i : Directivity pattern ID */ diff --git a/readme.txt b/readme.txt index 6e21541b0d09868c3a128b526f031f6a3e3b0f38..62d21f51bacdf05764e470b763bbd0ae659f0023 100644 --- a/readme.txt +++ b/readme.txt @@ -33,13 +33,13 @@ These files represent the 3GPP EVS Codec Extension for Immersive Voice and Audio Services (IVAS) floating-point C simulation. All code is writtten -in ISO/IEC C99. The system is implemented as five separate programs: +in ISO/IEC C99. The system is implemented as six separate programs: IVAS_cod IVAS Encoder IVAS_dec IVAS Decoder IVAS_rend IVAS External Renderer - ISAR_post_rend ISAR Post Renderer - ambi_converter Ambisonics format converter + IVAS_cod_fmtsw IVAS Encoder with support for format switching + ambi_converter example program for Ambisonics format conversion For encoding using the coder program, the input is a binary audio file (*.8k, *.16k, *.32k, *.48k) and the output is a binary @@ -123,7 +123,8 @@ should have the following structure: . `-- c-code - |-- Makefile + |-- readme.txt + |-- Makefile |-- Workspace_msvc |-- apps |-- lib_com @@ -134,21 +135,26 @@ should have the following structure: |-- lib_lc3plus |-- lib_rend |-- lib_util - |-- readme.txt - |-- .clang-format The package includes a Makefile for gcc, which has been verified on 32-bit Linux systems. The code can be compiled by entering the directory "c-code" and typing the command: make. The resulting encoder/decoder/renderer/ ISAR_post_renderer executables are named "IVAS_cod", "IVAS_dec", "IVAS_rend", -and "ISAR_post_rend". All reside in the c-code directory. +and "ISAR_post_rend". All reside in the c-code directory. In addition, this +directory will contain a version of the encoder with support for format switching +(named "IVAS_cod_fmtsw") and an example program for Ambisonics format conversion +(named "ambi_converter"). The package also includes a solution-file for Microsoft Visual Studio 2017 (x86). To compile the code, please open "Workspace_msvc\Workspace_msvc.sln" and build "encoder" for the encoder, "decoder" for the decoder, and "renderer" for the renderer executable. The resulting encoder/decoder/renderer/ISAR_post_renderer executables are "IVAS_cod.exe", "IVAS_dec.exe", "IVAS_rend.exe", and -"ISAR_post_rend.exe". All reside in the c-code main directory. +"ISAR_post_rend.exe". All reside in the c-code main directory. In addition, this +directory will contain a version of the encoder with support for format switching +(named "IVAS_cod_fmtsw.exe") and an example program for Ambisonics format conversion +(named "ambi_converter.exe"). + INTEGRATION AS LIBRARIES @@ -175,7 +181,7 @@ some potential race conditions. The usage of the "IVAS_cod" program is as follows: -------------------------------------------------- -Usage: IVAS_cod.exe [Options] R Fs input_file bitstream_file +Usage: IVAS_cod [Options] R Fs input_file bitstream_file Mandatory parameters: --------------------- @@ -261,8 +267,9 @@ EVS mono is default, for IVAS choose one of the following: -stereo, -ism, -sba, The usage of the "IVAS_dec" program is as follows: -------------------------------------------------- -Usage for EVS: IVAS_dec.exe [Options] Fs bitstream_file output_file -Usage for IVAS: IVAS_dec.exe [Options] OutputConf Fs bitstream_file output_file +Usage for EVS: IVAS_dec [Options] Fs bitstream_file output_file + OR usage for IVAS (below) with -evs option and OutputConf +Usage for IVAS: IVAS_dec [Options] OutputConf Fs bitstream_file output_file Mandatory parameters: --------------------- @@ -279,6 +286,7 @@ output_file : Output audio filename Options: -------- +-evs : Specify that the supplied bitstream is an EVS bitstream -VOIP : VoIP mode: RTP in G192 -VOIP_hf_only=0 : VoIP mode: EVS RTP Payload Format hf_only=0 in rtpdump -VOIP_hf_only=1 : VoIP mode: EVS or IVAS RTP Payload Format hf_only=1 in rtpdump @@ -286,7 +294,8 @@ Options: EVS RTP Payload Format or rtpdump files containing TS26.253 Annex A IVAS RTP Payload Format. The SDP parameter hf_only is required. Reading RFC4867 AMR/AMR-WB RTP payload format is not supported. --Tracefile TF : VoIP mode: Generate trace file named TF +-Tracefile TF : VoIP mode: Generate trace file named TF. Requires -no_delay_cmp to + be enabled so that trace contents remain in sync with audio output. -fec_cfg_file : Optimal channel aware configuration computed by the JBM as described in Section 6.3.1 of TS26.448. The output is written into a .txt file. Each line contains the FER indicator @@ -307,6 +316,8 @@ Options: -rvf File : Reference vector specified by external trajectory File works only in combination with '-otr ref_vec' and 'ref_vec_lev' modes -render_config File : Binaural renderer configuration parameters in File (only for binaural outputs) +-room_size (S|M|L) : Selects default reverb based on a room size (S - small | M - medium | L - large) + for BINAURAL_ROOM_REVERB output configuration -non_diegetic_pan P : panning mono non-diegetic sound to stereo -90<= P <=90, left or l or 90->left, right or r or -90->right, center or c or 0->middle -exof File : External orientation trajectory File for simulation of external orientations @@ -331,7 +342,7 @@ Options: -------- -i File : Input audio File (WAV, raw PCM or scene description file) -if Format : Audio Format of input file (e.g. 5_1 or HOA3 or META, use -l for a list) - META is related to the Scene description file, see scripts/testv/renderer_config_format_readme.txt + META is related to the Scene description file, see scripts/testv/renderer_config_format_readme.txt -im Files : Metadata files for ISM/MASA/OMASA/OSBA/BINAURAL_SPLIT_PCM (one file per object). For OMASA input, ISM files must be specified first. -o File : Output audio File @@ -345,6 +356,7 @@ Options: -rf File : Reference rotation trajectory File for simulation of head tracking (only for binaural outputs) -rvf File : Reference vector trajectory File for simulation of head tracking (only for binaural outputs) -render_config File : Binaural renderer configuration parameters in File (only for binaural outputs) +-room_size (S|M|L) : Selects default reverb based on a room size (S - small | M - medium | L - large) -non_diegetic_pan P : Panning mono non-diegetic sound to stereo -90<= P <= 90 left or l or 90->left, right or r or -90->right, center or c or 0 ->middle -exof File : External orientation trajectory File for simulation of external orientations @@ -369,8 +381,8 @@ Options: -q : Quiet mode, limit printouts to terminal, default is deactivated -The usage of the "ISAR_post_rend" program: ------------------------------------------- +The usage of the "ISAR_post_rend" program as follows: +----------------------------------------------------- Usage: ISAR_post_rend [options] @@ -411,8 +423,8 @@ omitted, the LFE input is downmixed to all channels with a factor of 1/N. Positi the LFE channel. Maximum number of supported loudskpeakers N is 16. An example custom loudspeaker layout file is available: ls_setup_16ch_8+4+4.txt -The usage of the "ambi_converter" program ------------------------------------------- +The usage of the "ambi_converter" program as follows: +----------------------------------------------------- Usage: ambi_converter input_file output_file input_convention output_convention @@ -425,7 +437,16 @@ the following conventions are supported: 4 : SID-SN3D 5 : SID-N3D -Either the input or the output convention must always be ACN-SN3D! +Either the input or the output convention must always be ACN-SN3D. + +The usage of the "IVAS_cod_fmtsw" program is as follows: +-------------------------------------------------------- + +Usage: IVAS_cod_fmtsw format_switching_file + +Mandatory parameters: +--------------------- +format_switching_file: Text file containing a valid encoder command line in each line RUNNING THE SELF TEST @@ -677,8 +698,26 @@ obj__azi= azimuth angle in degrees to be applied on object , obj__relazi=0|1 if 1, obj__azi is interpreted as a relative modification. default is absolute modification obj__ele= elevation angle in degrees to be applied on object , 0-based indexing obj__relele=0|1 if 1, obj__ele is interpreted as a relative modification. default is absolute modification +obj__radius= linear radius to be applied on object , 0-based indexing +obj__relradius=0|1 if 1, obj__radius is interpreted as a relative modification. default is absolute modification +obj__yaw= yaw angle in degrees to be applied on object , 0-based indexing +obj__relyaw=0|1 if 1, obj__yaw is interpreted as a relative modification. default is absolute modification +obj__pitch= pitch angle in degrees to be applied on object , 0-based indexing +obj__relpitch=0|1 if 1, obj__pitch is interpreted as a relative modification. default is absolute modification If a parameter is not specified, that parameter is not edited. An empty line in the file corresponds to not editing any parameter in the item. Example files are available in folder /scripts/object_edit. + +RTP streaming file +------------------- +IVAS supports a simple packing and unpacking for streaming file for the RTP. In this format a single RTP_streaming_packet +contains the length of an RTP packet followed by the actual RTP packet which is recorded as-is. This format is produced +by the encoder when using the -rtpdump switch and the decoder assumes this format in the input when -VOIP_hf_only=1 is set. + +typedef struct { + u_int32 length; /* size of the RTP packet in bytes */ + (u_int8 * length) RTP_packet; /* RTP packet (sized length * byte) */ +} RTP_streaming_packet; +