diff --git a/apps/decoder.c b/apps/decoder.c index fbb89222614de446151bb27cc3c3cadba373c909..5e1aafe2072f8cc3f4210245ea1ed888816d1221 100644 --- a/apps/decoder.c +++ b/apps/decoder.c @@ -398,9 +398,17 @@ int main( IVAS_RENDER_CONFIG_DATA renderConfig; /* sanity check */ +#ifdef TD5 + if ( arg.outputFormat != IVAS_DEC_OUTPUT_BINAURAL_ROOM && arg.outputFormat != IVAS_DEC_OUTPUT_BINAURAL ) +#else if ( arg.outputFormat != IVAS_DEC_OUTPUT_BINAURAL_ROOM ) +#endif { +#ifdef TD5 + fprintf( stderr, "\nExternal Renderer Config is supported only for BINAURAL and BINAURAL_ROOM. Exiting. \n\n" ); +#else fprintf( stderr, "\nExternal Renderer Config is supported only when BINAURAL_ROOM is used as output. Exiting. \n\n" ); +#endif goto cleanup; } @@ -1334,6 +1342,9 @@ static ivas_error decodeG192( ivas_error error = IVAS_ERR_UNKNOWN; uint16_t numObj = 0; IVAS_DEC_BS_FORMAT bsFormat = IVAS_DEC_BS_UNKOWN; +#ifdef TD5 + IVAS_POSITION Pos[IVAS_MAX_PARAM_SPATIAL_SUBFRAMES]; +#endif IsmFileWriter *ismWriters[IVAS_MAX_NUM_OBJECTS]; for ( i = 0; i < IVAS_MAX_NUM_OBJECTS; ++i ) @@ -1408,13 +1419,21 @@ static ivas_error decodeG192( { IVAS_QUATERNION Quaternions[IVAS_MAX_PARAM_SPATIAL_SUBFRAMES]; +#ifdef TD5 + if ( ( error = HeadRotationFileReading( headRotReader, Quaternions, Pos ) ) != IVAS_ERR_OK ) +#else if ( ( error = HeadRotationFileReading( headRotReader, Quaternions, frame ) ) != IVAS_ERR_OK ) +#endif { fprintf( stderr, "\nError %s while reading head orientation from %s\n", IVAS_DEC_GetErrorMessage( error ), HeadRotationFileReader_getFilePath( headRotReader ) ); goto cleanup; } +#ifdef TD5 + if ( ( error = IVAS_DEC_FeedHeadTrackData( hIvasDec, Quaternions, Pos ) ) != IVAS_ERR_OK ) +#else if ( ( error = IVAS_DEC_FeedHeadTrackData( hIvasDec, Quaternions ) ) != IVAS_ERR_OK ) +#endif { fprintf( stderr, "\nIVAS_DEC_FeedHeadTrackData failed: %s\n", IVAS_DEC_GetErrorMessage( error ) ); goto cleanup; diff --git a/apps/encoder.c b/apps/encoder.c index 1e0fb3e5240c00ea51ed5397119b00026444b3e5..17cec67a3405c9ad59ef08f66ed579c339d6e8f0 100644 --- a/apps/encoder.c +++ b/apps/encoder.c @@ -126,6 +126,9 @@ typedef struct #endif #endif bool pca; +#ifdef TD5 + bool ism_extended_metadata; +#endif } EncArguments; @@ -378,7 +381,11 @@ int main( } break; case IVAS_ENC_INPUT_ISM: +#ifdef TD5 + 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 ) +#else if ( ( error = IVAS_ENC_ConfigureForObjects( hIvasEnc, arg.inputFs, totalBitrate, arg.max_bwidth_user, bandwidth, arg.dtxConfig, arg.inputFormatConfig.ism.numObjects ) ) != IVAS_ERR_OK ) +#endif { fprintf( stderr, "\nIVAS_ENC_ConfigureForObjects failed: %s\n\n", IVAS_ENC_GetErrorMessage( error ) ); goto cleanup; @@ -876,6 +883,9 @@ static void initArgStruct( EncArguments *arg ) arg->caConfig = IVAS_ENC_GetDefaultChannelAwareConfig(); arg->ca_config_file = NULL; arg->mimeOutput = false; +#ifdef TD5 + arg->ism_extended_metadata = false; +#endif #ifdef DEBUGGING arg->forcedMode = IVAS_ENC_FORCE_UNFORCED; @@ -1263,6 +1273,13 @@ static bool parseCmdlIVAS_enc( if ( i < argc - 4 ) { +#ifdef TD5 + if ( argv[i][0] == '+' ) + { + argv[i]++; + arg->ism_extended_metadata = true; + } +#endif if ( !is_digits_only( argv[i] ) ) { fprintf( stderr, "Error: Number of ISM channels must be an integer number!\n\n" ); @@ -1643,8 +1660,14 @@ static void usage_enc( void ) fprintf( stdout, "EVS mono is default, for IVAS choose one of the following: -stereo, -ism, -sba, -masa, -mc\n" ); fprintf( stdout, "-stereo [Mode] : Stereo format, default is unified stereo \n" ); fprintf( stdout, " optional for Mode: 1: DFT Stereo, 2: TD Stereo, 3: MDCT Stereo\n" ); +#ifdef TD5 + fprintf( stdout, "-ism (+)Ch Files : ISM format \n" ); + fprintf( stdout, " where Ch specifies the number of ISMs (1-4)\n" ); + fprintf( stdout, " where positive (+) means extended metadata format is used (including orientation and radius) \n" ); +#else fprintf( stdout, "-ism Channels Files : ISM format \n" ); fprintf( stdout, " where Channels specifies the number of ISMs (1-4)\n" ); +#endif 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" ); diff --git a/apps/renderer.c b/apps/renderer.c index 1c9601b5906c03b53138378b614861a8a12bf475..7c662074af887ef7dd2f17e903579e3cfbc0c8f5 100644 --- a/apps/renderer.c +++ b/apps/renderer.c @@ -517,6 +517,9 @@ int main( int32_t delayTimeScale = 0; int16_t i, numChannels; ivas_error error = IVAS_ERR_OK; +#ifdef TD5 + IVAS_POSITION Pos[RENDERER_HEAD_POSITIONS_PER_FRAME]; +#endif #ifdef WMOPS reset_wmops(); @@ -622,40 +625,52 @@ int main( } /* === Configure === */ +#ifdef TD5 + if ( ( error = IVAS_REND_InitConfig( hIvasRend, ( args.outConfig.audioConfig == IVAS_REND_AUDIO_CONFIG_BINAURAL_ROOM ) || ( args.outConfig.audioConfig == IVAS_REND_AUDIO_CONFIG_BINAURAL ) ) ) != IVAS_ERR_OK ) +#else if ( ( error = IVAS_REND_InitConfig( hIvasRend, strlen( args.renderConfigFilePath ) != 0 ) ) != IVAS_ERR_OK ) { exit( -1 ); } +#endif - if ( args.renderConfigFilePath[0] != '\0' ) - { - IVAS_RENDER_CONFIG_DATA renderConfig; + if ( args.renderConfigFilePath[0] != '\0' ) + { + IVAS_RENDER_CONFIG_DATA renderConfig; - /* sanity check */ + /* sanity check */ +#ifdef TD5 + if ( ( args.outConfig.audioConfig != IVAS_REND_AUDIO_CONFIG_BINAURAL_ROOM ) && ( args.outConfig.audioConfig != IVAS_REND_AUDIO_CONFIG_BINAURAL ) ) +#else if ( args.outConfig.audioConfig != IVAS_REND_AUDIO_CONFIG_BINAURAL_ROOM ) - { +#endif + { +#ifdef TD5 + fprintf( stderr, "\nExternal Renderer Config is supported only when BINAURAL or BINAURAL_ROOM is used as output. Exiting. \n" ); +#else fprintf( stderr, "\nExternal Renderer Config is supported only when BINAURAL_ROOM is used as output. Exiting. \n" ); - exit( -1 ); - } +#endif + exit( -1 ); + } - if ( ( error = IVAS_REND_GetRenderConfig( hIvasRend, &renderConfig ) ) != IVAS_ERR_OK ) - { - fprintf( stderr, "\nIVAS_DEC_GetRenderConfig failed\n" ); - exit( -1 ); - } + if ( ( error = IVAS_REND_GetRenderConfig( hIvasRend, &renderConfig ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nIVAS_DEC_GetRenderConfig failed\n" ); + exit( -1 ); + } - if ( RenderConfigReader_read( renderConfigReader, &renderConfig ) != IVAS_ERR_OK ) - { - fprintf( stderr, "Failed to read renderer configuration from file %s\n", args.renderConfigFilePath ); - exit( -1 ); - } + if ( RenderConfigReader_read( renderConfigReader, &renderConfig ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Failed to read renderer configuration from file %s\n", args.renderConfigFilePath ); + exit( -1 ); + } - if ( ( error = IVAS_REND_FeedRenderConfig( hIvasRend, renderConfig ) ) != IVAS_ERR_OK ) - { - fprintf( stderr, "\nIVAS_DEC_FeedRenderConfig failed\n" ); - exit( -1 ); + if ( ( error = IVAS_REND_FeedRenderConfig( hIvasRend, renderConfig ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nIVAS_DEC_FeedRenderConfig failed\n" ); + exit( -1 ); + } } - } /* Set up output custom layout configuration */ if ( args.outConfig.audioConfig == IVAS_REND_AUDIO_CONFIG_LS_CUSTOM ) @@ -860,12 +875,21 @@ int main( if ( headRotReader != NULL ) { IVAS_QUATERNION quatBuffer[RENDERER_HEAD_POSITIONS_PER_FRAME]; +#ifdef TD5 + HeadRotationFileReading( headRotReader, quatBuffer, Pos ); + IVAS_REND_SetHeadRotation( hIvasRend, quatBuffer, Pos ); +#else HeadRotationFileReading( headRotReader, quatBuffer, frame ); IVAS_REND_SetHeadRotation( hIvasRend, quatBuffer ); +#endif } else { +#ifdef TD5 + IVAS_REND_SetHeadRotation( hIvasRend, NULL, NULL ); +#else IVAS_REND_SetHeadRotation( hIvasRend, NULL ); +#endif } for ( i = 0; i < args.inConfig.numMultiChannelBuses; ++i ) @@ -1687,6 +1711,11 @@ void getMetadataFromFileReader( objectMetadataBuffer->positions[objIdx].azimuth = ismMetadata.azimuth; objectMetadataBuffer->positions[objIdx].elevation = ismMetadata.elevation; +#ifdef TD5 + objectMetadataBuffer->positions[objIdx].radius = ismMetadata.radius; + objectMetadataBuffer->positions[objIdx].yaw = ismMetadata.yaw; + objectMetadataBuffer->positions[objIdx].pitch = ismMetadata.pitch; +#endif return; } @@ -1741,6 +1770,11 @@ static void IsmPositionProvider_getNextFrame( { objectMetadataBuffer->positions[objIdx].azimuth = 0.0f; objectMetadataBuffer->positions[objIdx].elevation = 0.0f; +#ifdef TD5 + objectMetadataBuffer->positions[objIdx].radius = 1.0f; + objectMetadataBuffer->positions[objIdx].yaw = 0.0f; + objectMetadataBuffer->positions[objIdx].pitch = 0.0f; +#endif } /* Wrap azimuth to lie within (-180, 180] range */ @@ -1755,6 +1789,20 @@ static void IsmPositionProvider_getNextFrame( /* Clamp elevation to lie within [-90, 90] range (can't be wrapped easily) */ objectMetadataBuffer->positions[objIdx].elevation = min( max( objectMetadataBuffer->positions[objIdx].elevation, -90 ), 90 ); +#ifdef TD5 + /* Wrap yaw to lie within (-180, 180] range */ + while ( objectMetadataBuffer->positions[objIdx].yaw < 0.0f ) + { + objectMetadataBuffer->positions[objIdx].yaw += 360.0f; + } + while ( objectMetadataBuffer->positions[objIdx].yaw >= 360.0f ) + { + objectMetadataBuffer->positions[objIdx].yaw -= 360.0f; + } + + /* Clamp pitch to lie within [-90, 90] range (can't be wrapped easily) */ + objectMetadataBuffer->positions[objIdx].pitch = min( max( objectMetadataBuffer->positions[objIdx].pitch, -90 ), 90 ); +#endif } ++positionProvider->frameCounter; @@ -1989,6 +2037,28 @@ static void parseObjectPosition( uint16_t *positionDuration ) { char *endptr; +#ifdef TD5 + int16_t read_values; + float meta_prm[7] = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f }; + + readNextMetadataChunk( line, "," ); + *positionDuration = (uint16_t) strtol( line, &endptr, 10 ); + readNextMetadataChunk( line, "\n" ); + + read_values = (int16_t) sscanf( line, "%f,%f,%f,%f,%f,%f,%f", &meta_prm[0], &meta_prm[1], &meta_prm[2], &meta_prm[3], &meta_prm[4], &meta_prm[5], &meta_prm[6] ); + + if ( read_values < 2 ) + { + fprintf( stderr, "Error reading metadata\n" ); + exit( -1 ); + } + + position->azimuth = meta_prm[0]; + position->elevation = meta_prm[1]; + position->radius = meta_prm[2]; + position->yaw = meta_prm[5]; + position->pitch = meta_prm[6]; +#else readNextMetadataChunk( line, "," ); *positionDuration = (uint16_t) strtol( line, &endptr, 10 ); @@ -2015,7 +2085,7 @@ static void parseObjectPosition( fprintf( stderr, "Error reading metadata\n" ); exit( -1 ); } - +#endif return; } diff --git a/lib_com/common_api_types.h b/lib_com/common_api_types.h index 8c1e1837f56eda1c02bd16bea4a7bcbaaba8d75e..dc1df1b5f0c5edf146307c211d4d7c1fa9e913ef 100644 --- a/lib_com/common_api_types.h +++ b/lib_com/common_api_types.h @@ -78,6 +78,10 @@ typedef struct _IVAS_ISM_METADATA float radius; float spread; float gainFactor; +#ifdef TD5 + float yaw; + float pitch; +#endif } IVAS_ISM_METADATA; typedef struct @@ -86,6 +90,14 @@ typedef struct } IVAS_QUATERNION; +#ifdef TD5 +typedef struct +{ + float x, y, z; + +} IVAS_POSITION; +#endif + typedef struct ivas_masa_metadata_frame_struct *IVAS_MASA_METADATA_HANDLE; #ifdef FIX_350_MASA_DELAY_COMP typedef struct ivas_masa_decoder_ext_out_meta_struct *MASA_DECODER_EXT_OUT_META_HANDLE; @@ -111,6 +123,11 @@ typedef struct { float azimuth; float elevation; +#ifdef TD5 + float radius; + float yaw; + float pitch; +#endif } IVAS_REND_AudioObjectPosition; typedef struct _IVAS_ROOM_ACOUSTICS_CONFIG @@ -132,6 +149,9 @@ typedef struct _IVAS_RENDER_CONFIG IVAS_RENDER_TYPE_OVERRIDE renderer_type_override; #endif IVAS_ROOM_ACOUSTICS_CONFIG_DATA room_acoustics; +#ifdef TD5 + float directivity[3]; +#endif } IVAS_RENDER_CONFIG_DATA, *IVAS_RENDER_CONFIG_HANDLE; typedef struct _IVAS_LS_CUSTOM_LAYOUT diff --git a/lib_com/ivas_cnst.h b/lib_com/ivas_cnst.h index b382b6660071540dce409fcd1be3acd7fda79fd2..b79adb5532b3ffbb8d55e830d6761f04835a33f8 100644 --- a/lib_com/ivas_cnst.h +++ b/lib_com/ivas_cnst.h @@ -320,6 +320,14 @@ typedef enum #define ISM_Q_STEP 2.5f #define ISM_Q_STEP_BORDER 5.0f +#ifdef TD5 +#define ISM_RADIUS_NBITS 6 +#define ISM_RADIUS_MIN 0.0f +#define ISM_RADIUS_DELTA 0.25f /* Max radius = (2^ISM_RADIUS_NBITS-1)*0.25 = 15.75 */ +#define ISM_EXTENDED_METADATA_BRATE IVAS_64k +#define ISM_EXTENDED_METADATA_BITS 1 +#endif + /* Parametric ISM */ #define MAX_PARAM_ISM_NBANDS 11 #define MAX_PARAM_ISM_NBANDS_WB 9 @@ -349,7 +357,12 @@ typedef enum enum { IND_ISM_NUM_OBJECTS, +#ifdef TD5 + IND_ISM_EXTENDED_FLAG = IND_ISM_NUM_OBJECTS + MAX_NUM_OBJECTS, + IND_ISM_METADATA_FLAG = IND_ISM_EXTENDED_FLAG + MAX_NUM_OBJECTS, /* EN2VE: Is this not supposed to be in the loop part below, since it is one per ISm? */ +#else IND_ISM_METADATA_FLAG = IND_ISM_NUM_OBJECTS + MAX_NUM_OBJECTS, +#endif IND_ISM_VAD_FLAG = IND_ISM_METADATA_FLAG + MAX_NUM_OBJECTS, IND_ISM_SCE_ID_DTX = IND_ISM_VAD_FLAG + MAX_NUM_OBJECTS, IND_ISM_NOISY_SPEECH_FLAG, @@ -361,6 +374,10 @@ enum IND_ISM_AZIMUTH = TAG_ISM_LOOP_START, IND_ISM_ELEVATION_DIFF_FLAG = TAG_ISM_LOOP_START, IND_ISM_ELEVATION = TAG_ISM_LOOP_START, +#ifdef TD5 + IND_ISM_RADIUS_DIFF_FLAG = TAG_ISM_LOOP_START, + IND_ISM_RADIUS = TAG_ISM_LOOP_START, +#endif TAG_ISM_LOOP_END = TAG_ISM_LOOP_START + 100, /* IVAS_fmToDo: to be reviewed once the final metadata are defined */ /* --------- end of loop for objects ----------- */ diff --git a/lib_com/ivas_ism_config.c b/lib_com/ivas_ism_config.c index b22d82a9da0c1dc1cade26bcaa9919b6b28c32a2..d6b0999f7ee17e8b52bcc538b6cb21887f71b36c 100644 --- a/lib_com/ivas_ism_config.c +++ b/lib_com/ivas_ism_config.c @@ -131,6 +131,12 @@ ivas_error ivas_ism_config( /* count ISm common signaling bits */ if ( hIsmMeta != NULL ) { +#ifdef TD5 + if ( ism_total_brate >= ISM_EXTENDED_METADATA_BRATE ) + { + nb_bits_metadata[0] += ISM_EXTENDED_METADATA_BITS; + } +#endif nb_bits_metadata[0] += n_ISms * ISM_METADATA_FLAG_BITS + num_obj; for ( ch = 0; ch < n_ISms; ch++ ) @@ -329,7 +335,11 @@ void ivas_ism_reset_metadata( { hIsmMeta->azimuth = 0.0f; hIsmMeta->elevation = 0.0f; - +#ifdef TD5 + hIsmMeta->yaw = 0.0f; + hIsmMeta->pitch = 0.0f; + hIsmMeta->radius = 1.0f; +#endif return; } diff --git a/lib_com/ivas_prot.h b/lib_com/ivas_prot.h old mode 100644 new mode 100755 index c5b7cef5db73fa5ba61bc357938e50afccfa0504..8ec50b98a099b07fcf7380733de35b1cad2d284c --- a/lib_com/ivas_prot.h +++ b/lib_com/ivas_prot.h @@ -781,7 +781,14 @@ float ism_dequant_meta( ivas_error ivas_set_ism_metadata( ISM_METADATA_HANDLE hIsmMeta, /* o : ISM metadata handle */ const float azimuth, /* i : azimuth value */ +#ifdef TD5 + const float elevation, /* i : elevation value */ + float radius_meta, /* i : radius */ + float yaw, /* i : yaw */ + float pitch /* i : pitch */ +#else const float elevation /* i : elevation value */ +#endif ); ivas_error ivas_ism_metadata_enc_create( @@ -812,7 +819,12 @@ ivas_error ivas_ism_metadata_enc( int16_t nb_bits_metadata[], /* o : number of metadata bits */ const int16_t localVAD[], /* i : VAD flag */ const int16_t ism_mode, /* i : ISM mode */ +#ifdef TD5 + const PARAM_ISM_CONFIG_HANDLE hParamIsm, /* i : Param ISM Config Handle */ + const int16_t ism_extended_metadata_flag /* i : Extended metadata flag */ +#else const PARAM_ISM_CONFIG_HANDLE hParamIsm /* i : Param ISM Config Handle */ +#endif ); ivas_error ivas_ism_metadata_dec( diff --git a/lib_com/ivas_rom_com.h b/lib_com/ivas_rom_com.h index 0fea291b30d444282cd3ee13a73c27aa2b0e9bdc..f6a9cb6ef113c261b7a26b291ad84843870d791b 100644 --- a/lib_com/ivas_rom_com.h +++ b/lib_com/ivas_rom_com.h @@ -317,7 +317,9 @@ extern const float McMASA_LFEGain_vectors[64]; extern const float ism_azimuth_borders[4]; extern const float ism_elevation_borders[4]; - +#ifdef TD5 +extern const float ism_radius_borders[4]; +#endif // TD5 /*----------------------------------------------------------------------------------* * Param ISM ROM tables *----------------------------------------------------------------------------------*/ diff --git a/lib_com/ivas_stat_com.h b/lib_com/ivas_stat_com.h index 8231588551aa246aa6f71ccd6ccd6ec0c457fc1b..244ba7ff768d6bdd2be5dfa1541f79626d5c29a9 100644 --- a/lib_com/ivas_stat_com.h +++ b/lib_com/ivas_stat_com.h @@ -43,7 +43,15 @@ /*----------------------------------------------------------------------------------* * Declaration of ISm common (encoder & decoder) structure *----------------------------------------------------------------------------------*/ - +#ifdef TD5 +typedef struct +{ + int16_t last_azimuth_idx; /* last frame index of coded azimuth */ + int16_t azimuth_diff_cnt; /* FEC counter of consecutive differentially azimuth coded frames */ + int16_t last_elevation_idx; /* last frame index of coded elevation */ + int16_t elevation_diff_cnt; /* FEC counter of consecutive differentially elevation coded frames */ +} ISM_METADATA_ANGLE, *ISM_METADATA_ANGLE_HANDLE; +#endif /* ISM metadata handle (storage for one frame of read ISM metadata) */ typedef struct { @@ -52,12 +60,19 @@ typedef struct float azimuth; /* azimuth value read from the input metadata file */ float elevation; /* azimuth value read from the input metadata file */ - +#ifdef TD5 + float radius; + float yaw; /* azimuth orientation value read from the input metadata file */ + float pitch; /* elevation orientation value read from the input metadata file */ + ISM_METADATA_ANGLE angle[2]; /* Angle structs for [0] azimuth/elevation and [1] yaw/pitch */ + int16_t last_radius_idx; /* last frame index of coded radius */ + int16_t radius_diff_cnt; /* FEC counter of consecutive differentially radius coded frames */ +#else int16_t last_azimuth_idx; /* last frame index of coded azimuth */ int16_t azimuth_diff_cnt; /* FEC counter of consecutive differentially azimuth coded frames */ int16_t last_elevation_idx; /* last frame index of coded elevation */ int16_t elevation_diff_cnt; /* FEC counter of consecutive differentially elevation coded frames */ - +#endif } ISM_METADATA_FRAME, *ISM_METADATA_HANDLE; diff --git a/lib_com/options.h b/lib_com/options.h old mode 100755 new mode 100644 index 950a2f28ebae4e525fee8f0d0512495b83a7df8a..1dd2d2e218aab7a95d5542e34749b75ec61b9119 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -149,8 +149,9 @@ #define BINAURALIZATION_DELAY_REPORT /* VA: Issue 255 - Changes the way the decoder delay is reported */ #define TUNE_360_OBJECT_WITH_NOISE /* VA: issue 360: consider objects being speech+noise for active speech coding */ #define FIX_350_MASA_DELAY_COMP /* Nokia: Issue 350: MASA audio/meta delay compensation */ - -#define FIX_376_SBA_ROTATE /*DLB: Fix for issue 376*/ +#define FIX_372_LIB_REND_VALIDATE_IO /* FhG: Issue 372: IVAS_rend segfaults with unsupported I/O configs - add validation checks of I/O config */ +#define FIX_376_SBA_ROTATE /*DLB: Fix for issue 376*/ +#define TD5 /* Eri: Contribution 17: Extended metadata for 6 DoF rendering in TD renderer */ /* ################## End DEVELOPMENT switches ######################### */ /* clang-format on */ diff --git a/lib_dec/ivas_ism_metadata_dec.c b/lib_dec/ivas_ism_metadata_dec.c index b60f66bdfb313ecd5421a11d37f8e4f91c386db1..7c8946fc437b46305b6467ecae21c12db52b6113 100644 --- a/lib_dec/ivas_ism_metadata_dec.c +++ b/lib_dec/ivas_ism_metadata_dec.c @@ -42,6 +42,14 @@ #endif #include "wmc_auto.h" +/* Local Functions */ +#ifdef TD5 +/*-----------------------------------------------------------------------* + * Local functions + *-----------------------------------------------------------------------*/ +static void decode_angle_indices( DEC_CORE_HANDLE st0, ISM_METADATA_ANGLE_HANDLE angle, int16_t *flag_abs_azimuth ); +int16_t decode_radius( DEC_CORE_HANDLE st0, int16_t *last_radius_idx, int16_t *flag_abs_radius ); +#endif /*-------------------------------------------------------------------------* * ivas_ism_metadata_dec() @@ -60,11 +68,24 @@ ivas_error ivas_ism_metadata_dec( const PARAM_ISM_CONFIG_HANDLE hParamIsm /* i : Param ISM Config Handle */ ) { +#ifdef TD5 + int16_t ch, nb_bits_start = 0, last_bit_pos; + int16_t idx_radius; +#else int16_t ch, nb_bits_start = 0, last_bit_pos, sgn, diff; +#endif int32_t element_brate[MAX_NUM_OBJECTS], total_brate[MAX_NUM_OBJECTS]; DEC_CORE_HANDLE st0; +#ifdef TD5 + int16_t ism_extended_metadata_flag; + int16_t flag_abs_radius; + int16_t flag_abs_orientation; + int16_t idx_azimuth, flag_abs_azimuth; + int16_t idx_elevation; +#else int16_t idx_azimuth, nbits_diff_azimuth, flag_abs_azimuth; int16_t idx_elevation, nbits_diff_elevation; +#endif int16_t next_bit_pos_orig; uint16_t i, bstr_meta[MAX_BITS_METADATA], *bstr_orig; ISM_METADATA_HANDLE hIsmMetaData; @@ -110,6 +131,9 @@ ivas_error ivas_ism_metadata_dec( bstr_orig = st0->bit_stream; next_bit_pos_orig = st0->next_bit_pos; st0->next_bit_pos = 0; +#ifdef TD5 + ism_extended_metadata_flag = 0; +#endif /* reverse the bitstream for easier reading of indices */ for ( i = 0; i < min( MAX_BITS_METADATA, last_bit_pos ); i++ ) @@ -148,7 +172,12 @@ ivas_error ivas_ism_metadata_dec( /* IVAS_fmToDo: more work needed when the number of transported objects is not constant */ return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "wrong number of objects signalled!" ); } - +#ifdef TD5 + if ( ism_total_brate >= ISM_EXTENDED_METADATA_BRATE ) + { + ism_extended_metadata_flag = get_next_indice( st0, ISM_EXTENDED_METADATA_BITS ); + } +#endif /* Read ISm present flags (one per object) */ for ( ch = 0; ch < *nchan_transport; ch++ ) { @@ -208,9 +237,46 @@ ivas_error ivas_ism_metadata_dec( } flag_abs_azimuth = 0; - +#ifdef TD5 + flag_abs_orientation = 0; + flag_abs_radius = 0; +#endif if ( hIsmMeta[ch]->ism_metadata_flag ) { +#ifdef TD5 + decode_angle_indices( st0, &( hIsmMetaData->angle[0] ), &flag_abs_azimuth ); + idx_azimuth = hIsmMetaData->angle[0].last_azimuth_idx; + idx_elevation = hIsmMetaData->angle[0].last_elevation_idx; + + /* Azimuth/Elevation dequantization */ + if ( ism_mode == ISM_MODE_PARAM ) + { + hParamIsm->azi_index[ch] = idx_azimuth; + hParamIsm->ele_index[ch] = idx_elevation; + } + else /* ISM_MODE_DISC */ + { + hIsmMetaData->azimuth = ism_dequant_meta( idx_azimuth, ism_azimuth_borders, 1 << ISM_AZIMUTH_NBITS ); + hIsmMetaData->elevation = ism_dequant_meta( idx_elevation, ism_elevation_borders, 1 << ISM_ELEVATION_NBITS ); + + if ( ism_extended_metadata_flag ) + { + decode_angle_indices( st0, &( hIsmMetaData->angle[1] ), &flag_abs_orientation ); + idx_azimuth = hIsmMetaData->angle[1].last_azimuth_idx; + idx_elevation = hIsmMetaData->angle[1].last_elevation_idx; + + hIsmMetaData->yaw = ism_dequant_meta( idx_azimuth, ism_azimuth_borders, 1 << ISM_AZIMUTH_NBITS ); + hIsmMetaData->pitch = ism_dequant_meta( idx_elevation, ism_elevation_borders, 1 << ISM_ELEVATION_NBITS ); + + idx_radius = decode_radius( st0, &hIsmMetaData->last_radius_idx, &flag_abs_radius ); + hIsmMetaData->radius = usdequant( idx_radius, ISM_RADIUS_MIN, ISM_RADIUS_DELTA ); + } + else + { + hIsmMetaData->radius = 1.0f; + } + } +#else /*----------------------------------------------------------------* * Azimuth decoding and dequantization *----------------------------------------------------------------*/ @@ -359,6 +425,7 @@ ivas_error ivas_ism_metadata_dec( /* updates */ hIsmMetaData->last_azimuth_idx = idx_azimuth; hIsmMetaData->last_elevation_idx = idx_elevation; +#endif } /* save number of metadata bits read */ @@ -443,8 +510,13 @@ ivas_error ivas_ism_metadata_dec( hParamIsm->ele_index[ch] = hParamIsm->ele_index[ch] + hParamIsm->last_el_sgn[ch] * hParamIsm->last_el_diff[ch]; /*hParamIsm->ele_index[ch] = hParamIsm->ele_index[ch] % hParamIsm->ele_alpha;*/ hParamIsm->ele_index[ch] = hParamIsm->ele_index[ch]; +#ifdef TD5 + hIsmMeta[ch]->angle[0].last_azimuth_idx = hParamIsm->azi_index[ch]; + hIsmMeta[ch]->angle[0].last_elevation_idx = hParamIsm->ele_index[ch]; +#else hIsmMeta[ch]->last_azimuth_idx = hParamIsm->azi_index[ch]; hIsmMeta[ch]->last_elevation_idx = hParamIsm->ele_index[ch]; +#endif } } } @@ -537,8 +609,16 @@ ivas_error ivas_ism_metadata_dec_create( } st_ivas->hIsmMetaData[ch]->last_ism_metadata_flag = 0; +#ifdef TD5 + st_ivas->hIsmMetaData[ch]->angle[0].last_azimuth_idx = 0; + st_ivas->hIsmMetaData[ch]->angle[0].last_elevation_idx = 1 << ( ISM_ELEVATION_NBITS - 1 ); + st_ivas->hIsmMetaData[ch]->angle[1].last_azimuth_idx = 0; + st_ivas->hIsmMetaData[ch]->angle[1].last_elevation_idx = 1 << ( ISM_ELEVATION_NBITS - 1 ); + st_ivas->hIsmMetaData[ch]->last_radius_idx = 8; /* Init to radius 1.0 */ +#else st_ivas->hIsmMetaData[ch]->last_azimuth_idx = 0; st_ivas->hIsmMetaData[ch]->last_elevation_idx = 1 << ( ISM_ELEVATION_NBITS - 1 ); +#endif ivas_ism_reset_metadata( st_ivas->hIsmMetaData[ch] ); } @@ -550,3 +630,211 @@ ivas_error ivas_ism_metadata_dec_create( return IVAS_ERR_OK; } + +#ifdef TD5 +static void decode_angle_indices( + DEC_CORE_HANDLE st0, /* i/o: bitstream handle */ + ISM_METADATA_ANGLE_HANDLE angle, /* i/o: angle handle */ + int16_t *flag_abs_azimuth /* o : Azimuth encoding mode */ +) +{ + /*----------------------------------------------------------------* + * Azimuth decoding and dequantization + *----------------------------------------------------------------*/ + int16_t idx_azimuth, nbits_diff_azimuth, diff, sgn; + int16_t idx_elevation, nbits_diff_elevation; + + /* Decode azimuth index */ + if ( get_next_indice( st0, 1 ) == 1 ) /* azimuth_abs_flag */ + { + idx_azimuth = get_next_indice( st0, ISM_AZIMUTH_NBITS ); + *flag_abs_azimuth = 1; + } + else + { + diff = 0; + sgn = 1; + + if ( get_next_indice( st0, 1 ) == 0 ) + { + nbits_diff_azimuth = 1; + } + else + { + nbits_diff_azimuth = 1; + + if ( get_next_indice( st0, 1 ) == 1 ) /* negative sign */ + { + sgn = -1; + } + + nbits_diff_azimuth++; + + /* read until the stop bit */ + while ( ( nbits_diff_azimuth < ISM_AZIMUTH_NBITS - 1 ) && ( get_next_indice( st0, 1 ) == 1 ) ) + { + diff++; + nbits_diff_azimuth++; + } + + if ( nbits_diff_azimuth < ISM_AZIMUTH_NBITS - 1 ) + { + /* count stop bit */ + nbits_diff_azimuth++; + } + } + idx_azimuth = angle->last_azimuth_idx + sgn * diff; + } + + /* azimuth is on a circle - check for diff coding for -180° -> 180° and vice versa changes */ + if ( idx_azimuth > ( 1 << ISM_AZIMUTH_NBITS ) - 1 ) + { + idx_azimuth -= ( 1 << ISM_AZIMUTH_NBITS ) - 1; /* +180° -> -180° */ + } + else if ( idx_azimuth < 0 ) + { + idx_azimuth += ( 1 << ISM_AZIMUTH_NBITS ) - 1; /* -180° -> +180° */ + } + + /* +180° == -180° */ + if ( idx_azimuth == ( 1 << ISM_AZIMUTH_NBITS ) - 1 ) + { + idx_azimuth = 0; + } + + /* sanity check in case of FER or BER */ + if ( idx_azimuth < 0 || idx_azimuth > ( 1 << ISM_AZIMUTH_NBITS ) - 1 ) + { + idx_azimuth = angle->last_azimuth_idx; + } + + /*----------------------------------------------------------------* + * Elevation decoding and dequantization + *----------------------------------------------------------------*/ + + /* Decode elevation index */ + if ( *flag_abs_azimuth == 0 && get_next_indice( st0, 1 ) == 1 ) /* elevation_abs_flag */ + { + idx_elevation = get_next_indice( st0, ISM_ELEVATION_NBITS ); + } + else + { + diff = 0; + sgn = 1; + + if ( get_next_indice( st0, 1 ) == 0 ) + { + nbits_diff_elevation = 1; + } + else + { + nbits_diff_elevation = 1; + + if ( get_next_indice( st0, 1 ) == 1 ) /* negative sign */ + { + sgn = -1; + } + + nbits_diff_elevation++; + + /* read until the stop bit */ + while ( ( nbits_diff_elevation < ISM_ELEVATION_NBITS ) && ( get_next_indice( st0, 1 ) == 1 ) ) + { + diff++; + nbits_diff_elevation++; + } + + if ( nbits_diff_elevation < ISM_ELEVATION_NBITS ) + { + /* count stop bit */ + nbits_diff_elevation++; + } + } + + idx_elevation = angle->last_elevation_idx + sgn * diff; + } + + /* sanity check in case of FER or BER */ + if ( idx_elevation < 0 || idx_elevation > ( 1 << ISM_ELEVATION_NBITS ) - 1 ) + { + idx_elevation = angle->last_elevation_idx; + } + /*----------------------------------------------------------------* + * Final updates + *----------------------------------------------------------------*/ + + /* updates */ + angle->last_azimuth_idx = idx_azimuth; + angle->last_elevation_idx = idx_elevation; + return; +} + +int16_t decode_radius( + DEC_CORE_HANDLE st0, /* i/o: bitstream handle */ + int16_t *last_radius_idx, /* i/o: last radius index */ + int16_t *flag_abs_radius /* o : Radius encoding mode */ +) +{ + /*----------------------------------------------------------------* + * Radius decoding and dequantization + *----------------------------------------------------------------*/ + int16_t idx_radius, nbits_diff_radius, diff, sgn; + + + /* Decode radius index */ + if ( get_next_indice( st0, 1 ) == 1 ) /* elevation_abs_flag */ + { + *flag_abs_radius = 1; + idx_radius = get_next_indice( st0, ISM_RADIUS_NBITS ); + } + else + { + diff = 0; + sgn = 1; + + if ( get_next_indice( st0, 1 ) == 0 ) + { + nbits_diff_radius = 1; + } + else + { + nbits_diff_radius = 1; + + if ( get_next_indice( st0, 1 ) == 1 ) /* negative sign */ + { + sgn = -1; + } + + nbits_diff_radius++; + + /* read until the stop bit */ + while ( ( nbits_diff_radius < ISM_RADIUS_NBITS ) && ( get_next_indice( st0, 1 ) == 1 ) ) + { + diff++; + nbits_diff_radius++; + } + + if ( nbits_diff_radius < ISM_RADIUS_NBITS ) + { + /* count stop bit */ + nbits_diff_radius++; + } + } + idx_radius = *last_radius_idx + sgn * diff; + } + + /* sanity check in case of FER or BER */ + if ( idx_radius < 0 || idx_radius > ( 1 << ISM_RADIUS_NBITS ) - 1 ) + { + idx_radius = *last_radius_idx; + } + + /*----------------------------------------------------------------* + * Final updates + *----------------------------------------------------------------*/ + + /* updates */ + *last_radius_idx = idx_radius; + return idx_radius; +} +#endif diff --git a/lib_dec/ivas_objectRenderer_internal.c b/lib_dec/ivas_objectRenderer_internal.c index 77e35867849f0609408845513cf2a3ba1ae41b77..d06a2b8f5b6d9ecdd2d1ccd30309004f2e771e72 100644 --- a/lib_dec/ivas_objectRenderer_internal.c +++ b/lib_dec/ivas_objectRenderer_internal.c @@ -53,8 +53,13 @@ ivas_error ivas_td_binaural_open( Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ ) { +#ifdef TD5 + return ivas_td_binaural_open_unwrap( &st_ivas->hHrtfTD, st_ivas->hDecoderConfig->output_Fs, st_ivas->nchan_transport, st_ivas->ivas_format, + st_ivas->transport_config, st_ivas->hRenderConfig->directivity, st_ivas->hTransSetup, &st_ivas->hBinRendererTd, &st_ivas->binaural_latency_ns ); +#else return ivas_td_binaural_open_unwrap( &st_ivas->hHrtfTD, st_ivas->hDecoderConfig->output_Fs, st_ivas->nchan_transport, st_ivas->ivas_format, st_ivas->transport_config, st_ivas->hTransSetup, &st_ivas->hBinRendererTd, &st_ivas->binaural_latency_ns ); +#endif } @@ -75,5 +80,10 @@ ivas_error ivas_td_binaural_renderer( st_ivas->hReverb, st_ivas->transport_config, st_ivas->hBinRendererTd, st_ivas->nchan_transport, LFE_CHANNEL, st_ivas->ivas_format, +#ifdef TD5 + st_ivas->hIsmMetaData, st_ivas->hDecoderConfig->Opt_Headrotation, ( st_ivas->hHeadTrackData != NULL ) ? st_ivas->hHeadTrackData->Quaternions : NULL, + ( st_ivas->hHeadTrackData != NULL ) ? st_ivas->hHeadTrackData->Pos : NULL, output, output_frame ); +#else st_ivas->hIsmMetaData, st_ivas->hDecoderConfig->Opt_Headrotation, ( st_ivas->hHeadTrackData != NULL ) ? st_ivas->hHeadTrackData->Quaternions : NULL, output, output_frame ); +#endif } diff --git a/lib_dec/lib_dec.c b/lib_dec/lib_dec.c index 2fba6491d44dde8989b5a5ba556da1d27d929edd..f6f233a1be2b96399ce8a3689bce838d920cbfba 100644 --- a/lib_dec/lib_dec.c +++ b/lib_dec/lib_dec.c @@ -834,7 +834,13 @@ ivas_error IVAS_DEC_GetObjectMetadata( { metadata->azimuth = hIsmMeta->azimuth; metadata->elevation = hIsmMeta->elevation; +#ifdef TD5 + metadata->radius = hIsmMeta->radius; + metadata->yaw = hIsmMeta->yaw; + metadata->pitch = hIsmMeta->pitch; +#else metadata->radius = 0.f; +#endif metadata->spread = 0.f; metadata->gainFactor = 1.f; } @@ -884,8 +890,13 @@ ivas_error IVAS_DEC_GetMasaMetadata( *---------------------------------------------------------------------*/ ivas_error IVAS_DEC_FeedHeadTrackData( - IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ - IVAS_QUATERNION *orientation /* i : head-tracking data */ + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ +#ifdef TD5 + IVAS_QUATERNION *orientation, /* i : head-tracking data, listener orientation */ + IVAS_POSITION *Pos /* i : listener position */ +#else + IVAS_QUATERNION *orientation /* i : head-tracking data, listener orientation */ +#endif ) { HEAD_TRACK_DATA_HANDLE hHeadTrackData; @@ -910,6 +921,11 @@ ivas_error IVAS_DEC_FeedHeadTrackData( hHeadTrackData->Quaternions[i].x = orientation[i].x; hHeadTrackData->Quaternions[i].y = orientation[i].y; hHeadTrackData->Quaternions[i].z = orientation[i].z; +#ifdef TD5 + hHeadTrackData->Pos[i].x = Pos[i].x; + hHeadTrackData->Pos[i].y = Pos[i].y; + hHeadTrackData->Pos[i].z = Pos[i].z; +#endif } hIvasDec->st_ivas->hHeadTrackData->num_quaternions = 0; @@ -1100,6 +1116,9 @@ ivas_error IVAS_DEC_GetRenderConfig( mvr2r( hRCin->roomAcoustics.pFc_input, hRCout->room_acoustics.pFc_input, CLDFB_NO_CHANNELS_MAX ); mvr2r( hRCin->roomAcoustics.pAcoustic_rt60, hRCout->room_acoustics.pAcoustic_rt60, CLDFB_NO_CHANNELS_MAX ); mvr2r( hRCin->roomAcoustics.pAcoustic_dsr, hRCout->room_acoustics.pAcoustic_dsr, CLDFB_NO_CHANNELS_MAX ); +#ifdef TD5 + mvr2r( hRCin->directivity, hRCout->directivity, 3 ); +#endif return IVAS_ERR_OK; } @@ -1144,6 +1163,9 @@ ivas_error IVAS_DEC_FeedRenderConfig( mvr2r( renderConfig.room_acoustics.pFc_input, hRenderConfig->roomAcoustics.pFc_input, CLDFB_NO_CHANNELS_MAX ); mvr2r( renderConfig.room_acoustics.pAcoustic_rt60, hRenderConfig->roomAcoustics.pAcoustic_rt60, CLDFB_NO_CHANNELS_MAX ); mvr2r( renderConfig.room_acoustics.pAcoustic_dsr, hRenderConfig->roomAcoustics.pAcoustic_dsr, CLDFB_NO_CHANNELS_MAX ); +#ifdef TD5 + mvr2r( renderConfig.directivity, hRenderConfig->directivity, 3 ); +#endif return IVAS_ERR_OK; } diff --git a/lib_dec/lib_dec.h b/lib_dec/lib_dec.h index e9aba91f9e8012edce083f6c84261fee9b4a7c36..1571c669b724c801ff945b8e5e7850775d50a1a2 100644 --- a/lib_dec/lib_dec.h +++ b/lib_dec/lib_dec.h @@ -177,7 +177,12 @@ ivas_error IVAS_DEC_GetMasaMetadata( /*! r: error code */ ivas_error IVAS_DEC_FeedHeadTrackData( IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ +#ifdef TD5 + IVAS_QUATERNION *orientation, /* i : head-tracking data */ + IVAS_POSITION *Pos /* i : listener position */ +#else IVAS_QUATERNION *orientation /* i : head-tracking data */ +#endif ); /*! r: error code */ diff --git a/lib_enc/ivas_ism_enc.c b/lib_enc/ivas_ism_enc.c index 497f47e38698d6c822e1302c689c73feccf5ec02..42f877aa1730524c7cbf9b8bafcb4bcb06a0920a 100644 --- a/lib_enc/ivas_ism_enc.c +++ b/lib_enc/ivas_ism_enc.c @@ -210,11 +210,19 @@ ivas_error ivas_ism_enc( } else if ( st_ivas->ism_mode == ISM_MODE_PARAM ) { +#ifdef TD5 + ivas_ism_metadata_enc( st_ivas->hEncoderConfig->ivas_total_brate, st_ivas->nchan_transport, st_ivas->hIsmMetaData, st_ivas->hSCE, st_ivas->hSCE[st_ivas->nSCE - 1]->hMetaData, nb_bits_metadata, vad_flag, st_ivas->ism_mode, st_ivas->hDirAC->hParamIsm, st_ivas->hEncoderConfig->ism_extended_metadata_flag ); +#else ivas_ism_metadata_enc( st_ivas->hEncoderConfig->ivas_total_brate, st_ivas->nchan_transport, st_ivas->hIsmMetaData, st_ivas->hSCE, st_ivas->hSCE[st_ivas->nSCE - 1]->hMetaData, nb_bits_metadata, vad_flag, st_ivas->ism_mode, st_ivas->hDirAC->hParamIsm ); +#endif } else /* ISM_MODE_DISC */ { +#ifdef TD5 + ivas_ism_metadata_enc( st_ivas->hEncoderConfig->ivas_total_brate, st_ivas->nchan_transport, st_ivas->hIsmMetaData, st_ivas->hSCE, st_ivas->hSCE[st_ivas->nSCE - 1]->hMetaData, nb_bits_metadata, vad_flag, st_ivas->ism_mode, NULL, st_ivas->hEncoderConfig->ism_extended_metadata_flag ); +#else ivas_ism_metadata_enc( st_ivas->hEncoderConfig->ivas_total_brate, st_ivas->nchan_transport, st_ivas->hIsmMetaData, st_ivas->hSCE, st_ivas->hSCE[st_ivas->nSCE - 1]->hMetaData, nb_bits_metadata, vad_flag, st_ivas->ism_mode, NULL ); +#endif } /*----------------------------------------------------------------* diff --git a/lib_enc/ivas_ism_metadata_enc.c b/lib_enc/ivas_ism_metadata_enc.c index 2c7150b6c3107748a1db8dcf36c5a7a2a55c15fd..3472de0c5a1fc3bafa98b8158edde9aa2e758e0c 100644 --- a/lib_enc/ivas_ism_metadata_enc.c +++ b/lib_enc/ivas_ism_metadata_enc.c @@ -49,15 +49,30 @@ * Local constants *-----------------------------------------------------------------------*/ +#ifdef TD5 +#define ISM_NUM_PARAM 5 /* number of coded metadata parameters */ +#else #define ISM_NUM_PARAM 2 /* number of coded metadata parameters */ +#endif #define ISM_MAX_AZIMUTH_DIFF_IDX ( ISM_AZIMUTH_NBITS - 1 /*zero*/ - 1 /*sign*/ ) #define ISM_MAX_ELEVATION_DIFF_IDX ( ISM_ELEVATION_NBITS - 1 /*zero*/ - 1 /*sign*/ ) +#ifdef TD5 +#define ISM_MAX_RADIUS_DIFF_IDX ( ISM_RADIUS_NBITS - 1 /*zero*/ - 1 /*sign*/ ) +#endif #define ISM_FEC_MAX 10 #define INTER_OBJECT_PARAM_CHECK ( ( ISM_FEC_MAX / 2 ) - 2 ) /* note: constant must be less than (ISM_FEC_MAX / number of coded parameters) */ +#ifdef TD5 +/*-----------------------------------------------------------------------* + * Local functions + *-----------------------------------------------------------------------*/ +static void encode_angle_indices( BSTR_ENC_HANDLE hBstr, ISM_METADATA_ANGLE_HANDLE angle, const int16_t last_ism_metadata_flag, const int16_t ini_frame, const int16_t idx_azimuth_abs, const int16_t idx_elevation_abs, int16_t *flag_abs_azimuth, int16_t *flag_abs_elevation ); +static void encode_radius( BSTR_ENC_HANDLE hBstr, int16_t *last_radius_idx, int16_t *radius_diff_cnt, const int16_t last_ism_metadata_flag, const int16_t idx_radius_abs, int16_t *flag_abs_radius ); + +#endif /*-------------------------------------------------------------------------* * ivas_set_ism_metadata() @@ -68,7 +83,14 @@ ivas_error ivas_set_ism_metadata( ISM_METADATA_HANDLE hIsmMeta, /* o : ISM metadata handle */ const float azimuth, /* i : azimuth value */ - const float elevation /* i : elevation value */ +#ifdef TD5 + const float elevation, /* i : elevation */ + float radius_meta, /* i : radius */ + float yaw, /* i : yaw */ + float pitch /* i : pitch */ +#else + const float elevation /* i : elevation value */ +#endif ) { if ( hIsmMeta == NULL ) @@ -81,7 +103,11 @@ ivas_error ivas_set_ism_metadata( /* save read metadata parameters to the internal codec structure */ hIsmMeta->azimuth = azimuth; hIsmMeta->elevation = elevation; - +#ifdef TD5 + hIsmMeta->radius = radius_meta; + hIsmMeta->yaw = yaw; + hIsmMeta->pitch = pitch; +#endif return IVAS_ERR_OK; } @@ -146,20 +172,37 @@ static void rate_ism_importance( *-------------------------------------------------------------------------*/ ivas_error ivas_ism_metadata_enc( - const int32_t ism_total_brate, /* i : ISms total bitrate */ - const int16_t nchan_transport, /* i : number of transport channels */ - ISM_METADATA_HANDLE hIsmMeta[], /* i/o: ISM metadata handles */ - SCE_ENC_HANDLE hSCE[], /* i/o: SCE encoder handles */ - BSTR_ENC_HANDLE hBstr, /* i/o: bitstream handle */ - int16_t nb_bits_metadata[], /* o : number of metadata bits */ - const int16_t localVAD[], /* i : VAD flag */ - const int16_t ism_mode, /* i : ISM mode */ + const int32_t ism_total_brate, /* i : ISms total bitrate */ + const int16_t nchan_transport, /* i : number of transport channels */ + ISM_METADATA_HANDLE hIsmMeta[], /* i/o: ISM metadata handles */ + SCE_ENC_HANDLE hSCE[], /* i/o: SCE encoder handles */ + BSTR_ENC_HANDLE hBstr, /* i/o: bitstream handle */ + int16_t nb_bits_metadata[], /* o : number of metadata bits */ + const int16_t localVAD[], /* i : VAD flag */ + const int16_t ism_mode, /* i : ISM mode */ +#ifdef TD5 + const PARAM_ISM_CONFIG_HANDLE hParamIsm, /* i : Param ISM Enc Handle */ + const int16_t ism_extended_metadata_flag /* i : Extended metadata flag */ +#else const PARAM_ISM_CONFIG_HANDLE hParamIsm /* i : Param ISM Enc Handle */ +#endif ) { +#ifdef TD5 +#ifdef TUNE_360_OBJECT_WITH_NOISE + int16_t i, ch, nb_bits_start = 0; +#else + int16_t i, ch, nb_bits_start = 0, diff; +#endif + int16_t idx_azimuth_abs = 0, flag_abs_azimuth[MAX_NUM_OBJECTS]; + int16_t idx_elevation_abs = 0, flag_abs_elevation[MAX_NUM_OBJECTS]; + int16_t flag_abs_azimuth_orientation[MAX_NUM_OBJECTS]; + int16_t idx_radius_abs = 0, flag_abs_radius[MAX_NUM_OBJECTS]; +#else int16_t i, ch, nb_bits_start = 0, diff; int16_t idx_azimuth, idx_azimuth_abs = 0, flag_abs_azimuth[MAX_NUM_OBJECTS], nbits_diff_azimuth; int16_t idx_elevation, idx_elevation_abs = 0, flag_abs_elevation[MAX_NUM_OBJECTS], nbits_diff_elevation; +#endif float valQ; ISM_METADATA_HANDLE hIsmMetaData; int32_t element_brate[MAX_NUM_OBJECTS], total_brate[MAX_NUM_OBJECTS]; @@ -198,6 +241,11 @@ ivas_error ivas_ism_metadata_enc( set_s( nb_bits_metadata, 0, nchan_transport ); set_s( flag_abs_azimuth, 0, num_obj ); set_s( flag_abs_elevation, 0, num_obj ); +#ifdef TD5 + set_s( flag_abs_azimuth_orientation, 0, num_obj ); + set_s( flag_abs_radius, 0, num_obj ); +#endif + /*----------------------------------------------------------------* * Set Metadata presence / importance flag @@ -211,6 +259,35 @@ ivas_error ivas_ism_metadata_enc( } else if ( ism_mode == ISM_MODE_DISC ) { +#ifdef TD5 +#ifdef TUNE_360_OBJECT_WITH_NOISE + /* In case of low level noise for low bitrate inactive frames, do not sent metadata */ + if ( localVAD[ch] == 0 && !( hSCE[ch]->hCoreCoder[0]->tcxonly ) && ( hSCE[ch]->hCoreCoder[0]->lp_noise <= 10 ) ) + { + hIsmMeta[ch]->ism_metadata_flag = 0; + } +#else + if ( hIsmMeta[ch]->ism_metadata_flag ) + { + /* at highest bitrates (with TCX core only) metadata are sent also for inactive frames */ + if ( localVAD[ch] == 0 && !( hSCE[ch]->hCoreCoder[0]->tcxonly ) ) + { + /* send metadata even in inactive segments when noise is audible and metadata are changing */ + diff = (int16_t) fabsf( hIsmMeta[ch]->azimuth - ism_dequant_meta( hIsmMeta[ch]->angle[0].last_azimuth_idx, ism_azimuth_borders, 1 << ISM_AZIMUTH_NBITS ) ); + diff = max( diff, (int16_t) fabsf( hIsmMeta[ch]->elevation - ism_dequant_meta( hIsmMeta[ch]->angle[0].last_elevation_idx, ism_elevation_borders, 1 << ISM_ELEVATION_NBITS ) ) ); + if ( ism_total_brate >= ISM_EXTENDED_METADATA_BRATE && ism_extended_metadata_flag ) + { + diff = max( diff, (int16_t) fabsf( hIsmMeta[ch]->yaw - ism_dequant_meta( hIsmMeta[ch]->angle[1].last_azimuth_idx, ism_azimuth_borders, 1 << ISM_AZIMUTH_NBITS ) ) ); + diff = max( diff, (int16_t) fabsf( hIsmMeta[ch]->pitch - ism_dequant_meta( hIsmMeta[ch]->angle[1].last_elevation_idx, ism_elevation_borders, 1 << ISM_ELEVATION_NBITS ) ) ); + } + if ( !( hSCE[ch]->hCoreCoder[0]->lp_noise > 15 && diff >= 10 ) ) + { + hIsmMeta[ch]->ism_metadata_flag = 0; + } + } + } +#endif +#else #ifdef TUNE_360_OBJECT_WITH_NOISE hIsmMeta[ch]->ism_metadata_flag = localVAD[ch] || hSCE[ch]->hCoreCoder[0]->lp_noise > 10; #else @@ -234,6 +311,7 @@ ivas_error ivas_ism_metadata_enc( /* at highest bitrates (with TCX core only) metadata are sent in every frame */ hIsmMeta[ch]->ism_metadata_flag = 1; } +#endif } } @@ -274,7 +352,12 @@ ivas_error ivas_ism_metadata_enc( push_indice( hBstr, IND_ISM_NUM_OBJECTS, 1, 1 ); } push_indice( hBstr, IND_ISM_NUM_OBJECTS, 0, 1 ); - +#ifdef TD5 + if ( ism_total_brate >= ISM_EXTENDED_METADATA_BRATE ) + { + push_indice( hBstr, IND_ISM_EXTENDED_FLAG, ism_extended_metadata_flag, ISM_EXTENDED_METADATA_BITS ); + } +#endif /* write ISm metadata flag (one per object) */ for ( ch = 0; ch < nchan_transport; ch++ ) { @@ -323,6 +406,39 @@ ivas_error ivas_ism_metadata_enc( if ( hIsmMeta[ch]->ism_metadata_flag ) { + +#ifdef TD5 + /*----------------------------------------------------------------* + * Obtain quantizer indices for azimuth and elevation + *----------------------------------------------------------------*/ + if ( ism_mode == ISM_MODE_DISC ) + { + idx_azimuth_abs = ism_quant_meta( hIsmMetaData->azimuth, &valQ, ism_azimuth_borders, 1 << ISM_AZIMUTH_NBITS ); + idx_elevation_abs = ism_quant_meta( hIsmMetaData->elevation, &valQ, ism_elevation_borders, 1 << ISM_ELEVATION_NBITS ); + } + else /* ISM_MODE_PARAM */ + { + idx_azimuth_abs = hParamIsm->azi_index[ch]; + idx_elevation_abs = hParamIsm->ele_index[ch]; + } + + encode_angle_indices( hBstr, &( hIsmMetaData->angle[0] ), hIsmMetaData->last_ism_metadata_flag, hSCE[0]->hCoreCoder[0]->ini_frame, idx_azimuth_abs, idx_elevation_abs, &flag_abs_azimuth[ch], &flag_abs_elevation[ch] ); + + /* Encode orientation and radius, if above certain bit rate etc, discrete ISM */ + if ( ism_mode == ISM_MODE_DISC && ism_extended_metadata_flag ) + { + idx_azimuth_abs = ism_quant_meta( hIsmMetaData->yaw, &valQ, ism_azimuth_borders, 1 << ISM_AZIMUTH_NBITS ); + idx_elevation_abs = ism_quant_meta( hIsmMetaData->pitch, &valQ, ism_elevation_borders, 1 << ISM_ELEVATION_NBITS ); + idx_radius_abs = usquant( hIsmMetaData->radius, &valQ, ISM_RADIUS_MIN, ISM_RADIUS_DELTA, 1 << ISM_RADIUS_NBITS ); + encode_angle_indices( hBstr, &( hIsmMetaData->angle[1] ), hIsmMetaData->last_ism_metadata_flag, hSCE[0]->hCoreCoder[0]->ini_frame, idx_azimuth_abs, idx_elevation_abs, &flag_abs_azimuth_orientation[ch], &flag_abs_elevation[ch] ); + encode_radius( hBstr, &hIsmMetaData->last_radius_idx, &hIsmMetaData->radius_diff_cnt, hIsmMetaData->last_ism_metadata_flag, idx_radius_abs, &flag_abs_radius[ch] ); + } + /* save number of metadata bits written */ + if ( ism_mode == ISM_MODE_DISC ) + { + nb_bits_metadata[ch] = hBstr->nb_bits_tot - nb_bits_start; + } +#else /*----------------------------------------------------------------* * Azimuth quantization and encoding *----------------------------------------------------------------*/ @@ -567,6 +683,7 @@ ivas_error ivas_ism_metadata_enc( { nb_bits_metadata[ch] = hBstr->nb_bits_tot - nb_bits_start; } +#endif } } @@ -579,7 +696,11 @@ ivas_error ivas_ism_metadata_enc( while ( i == 0 || i < num_obj / INTER_OBJECT_PARAM_CHECK ) { int16_t num, abs_num, abs_first, abs_next, pos_zero; +#ifdef TD5 + int16_t abs_matrice[INTER_OBJECT_PARAM_CHECK * ISM_NUM_PARAM]; +#else int16_t abs_matrice[INTER_OBJECT_PARAM_CHECK * 2]; +#endif num = min( INTER_OBJECT_PARAM_CHECK, num_obj - i * INTER_OBJECT_PARAM_CHECK ); i++; @@ -627,12 +748,20 @@ ivas_error ivas_ism_metadata_enc( if ( abs_next % ISM_NUM_PARAM == 0 ) { +#ifdef TD5 + hIsmMeta[ch]->angle[0].azimuth_diff_cnt = abs_num - 1; +#else hIsmMeta[ch]->azimuth_diff_cnt = abs_num - 1; +#endif } if ( abs_next % ISM_NUM_PARAM == 1 ) { +#ifdef TD5 + hIsmMeta[ch]->angle[0].elevation_diff_cnt = abs_num - 1; +#else hIsmMeta[ch]->elevation_diff_cnt = abs_num - 1; +#endif /*hIsmMeta[ch]->elevation_diff_cnt = min( hIsmMeta[ch]->elevation_diff_cnt, ISM_FEC_MAX );*/ } @@ -767,10 +896,23 @@ ivas_error ivas_ism_metadata_enc_create( return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for ISm MetaData\n" ) ); } +#ifdef TD5 + st_ivas->hIsmMetaData[ch]->angle[0].last_azimuth_idx = 0; + st_ivas->hIsmMetaData[ch]->angle[0].azimuth_diff_cnt = ISM_FEC_MAX; + st_ivas->hIsmMetaData[ch]->angle[0].last_elevation_idx = 0; + st_ivas->hIsmMetaData[ch]->angle[0].elevation_diff_cnt = ISM_FEC_MAX - 1; + st_ivas->hIsmMetaData[ch]->last_radius_idx = 0; + st_ivas->hIsmMetaData[ch]->radius_diff_cnt = ISM_FEC_MAX - 2; + st_ivas->hIsmMetaData[ch]->angle[1].last_azimuth_idx = 0; + st_ivas->hIsmMetaData[ch]->angle[1].azimuth_diff_cnt = ISM_FEC_MAX - 2; + st_ivas->hIsmMetaData[ch]->angle[1].last_elevation_idx = 0; + st_ivas->hIsmMetaData[ch]->angle[1].elevation_diff_cnt = ISM_FEC_MAX - 2; +#else st_ivas->hIsmMetaData[ch]->last_azimuth_idx = 0; st_ivas->hIsmMetaData[ch]->azimuth_diff_cnt = ISM_FEC_MAX; st_ivas->hIsmMetaData[ch]->last_elevation_idx = 0; st_ivas->hIsmMetaData[ch]->elevation_diff_cnt = ISM_FEC_MAX - 1; +#endif st_ivas->hIsmMetaData[ch]->last_ism_metadata_flag = 0; ivas_ism_reset_metadata( st_ivas->hIsmMetaData[ch] ); @@ -783,3 +925,346 @@ ivas_error ivas_ism_metadata_enc_create( return IVAS_ERR_OK; } + +#ifdef TD5 +static void encode_radius( + BSTR_ENC_HANDLE hBstr, /* i/o: bitstream handle */ + int16_t *last_radius_idx, /* i/o: last radius index */ + int16_t *radius_diff_cnt, /* i/o: radius diff coding counter */ + const int16_t last_ism_metadata_flag, /* last frame ism_metadata_flag */ + const int16_t idx_radius_abs, /* i : Azimuth index */ + int16_t *flag_abs_radius /* o : Radius encoding mode */ +) +{ + int16_t idx_radius, nbits_diff_radius, diff; + + + /*----------------------------------------------------------------* + * Radius index encoding + *----------------------------------------------------------------*/ + idx_radius = idx_radius_abs; + + nbits_diff_radius = 0; + + *flag_abs_radius = 0; /* differential coding by default */ + + if ( *radius_diff_cnt == ISM_FEC_MAX /* make differential encoding in ISM_FEC_MAX consecutive frames at maximum (in order to control the decoding in FEC) */ + || last_ism_metadata_flag == 0 /* If last frame had no metadata coded, do not use differential coding */ + ) + { + *flag_abs_radius = 1; + } + + diff = idx_radius_abs - *last_radius_idx; + + /* try differential coding */ + if ( *flag_abs_radius == 0 ) + { + if ( diff == 0 ) + { + idx_radius = 0; + nbits_diff_radius = 1; + } + else if ( ABSVAL( diff ) <= ISM_MAX_RADIUS_DIFF_IDX ) + { + idx_radius = 1 << 1; + nbits_diff_radius = 1; + + if ( diff < 0 ) + { + idx_radius += 1; /* negative sign */ + diff *= -1; + } + else + { + idx_radius += 0; /* positive sign */ + } + + idx_radius = idx_radius << diff; + nbits_diff_radius++; + + /* unary coding of "diff */ + idx_radius += ( ( 1 << diff ) - 1 ); + nbits_diff_radius += diff; + + if ( nbits_diff_radius < ISM_RADIUS_NBITS ) + { + /* add stop bit */ + idx_radius = idx_radius << 1; + nbits_diff_radius++; + } + } + else + { + *flag_abs_radius = 1; + } + } + + /* update counter */ + if ( *flag_abs_radius == 0 ) + { + ( *radius_diff_cnt )++; + *radius_diff_cnt = min( *radius_diff_cnt, ISM_FEC_MAX ); + } + else + { + *radius_diff_cnt = 0; + } + + /* Write radius */ + push_indice( hBstr, IND_ISM_RADIUS_DIFF_FLAG, *flag_abs_radius, 1 ); + + if ( *flag_abs_radius ) + { + push_indice( hBstr, IND_ISM_RADIUS, idx_radius, ISM_RADIUS_NBITS ); + } + else + { + push_indice( hBstr, IND_ISM_RADIUS, idx_radius, nbits_diff_radius ); + } + + /*----------------------------------------------------------------* + * Updates + *----------------------------------------------------------------*/ + *last_radius_idx = idx_radius_abs; + return; +} + +static void encode_angle_indices( + BSTR_ENC_HANDLE hBstr, /* i/o: bitstream handle */ + ISM_METADATA_ANGLE_HANDLE angle, /* i/o: angle handle */ + const int16_t last_ism_metadata_flag, /* last frame ism_metadata_flag */ + const int16_t ini_frame, /* i : initialization frames counter */ + const int16_t idx_azimuth_abs, /* i : Azimuth index */ + const int16_t idx_elevation_abs, /* i : Elevation index */ + int16_t *flag_abs_azimuth, /* o : Azimuth encoding mode */ + int16_t *flag_abs_elevation /* o : Elevation encoding mode */ +) +{ + int16_t idx_azimuth, nbits_diff_azimuth, diff; + int16_t idx_elevation, nbits_diff_elevation; + + + /*----------------------------------------------------------------* + * Azimuth index encoding + *----------------------------------------------------------------*/ + + idx_azimuth = idx_azimuth_abs; + + nbits_diff_azimuth = 0; + + *flag_abs_azimuth = 0; /* differential coding by default */ + if ( angle->azimuth_diff_cnt == ISM_FEC_MAX /* make differential encoding in ISM_FEC_MAX consecutive frames at maximum (in order to control the decoding in FEC) */ + || last_ism_metadata_flag == 0 /* If last frame had no metadata coded, do not use differential coding */ + ) + { + *flag_abs_azimuth = 1; + } + + /* try differential coding */ + if ( *flag_abs_azimuth == 0 ) + { + diff = idx_azimuth_abs - angle->last_azimuth_idx; + + /* azimuth is on a circle - check for diff coding for -180° -> 180° and vice versa changes */ + if ( abs( diff ) > ( ( 1 << ISM_AZIMUTH_NBITS ) - 1 ) - ISM_MAX_AZIMUTH_DIFF_IDX ) + { + if ( diff > 0 ) + { + diff -= ( 1 << ISM_AZIMUTH_NBITS ) - 1; + } + else + { + diff += ( 1 << ISM_AZIMUTH_NBITS ) - 1; + } + } + + if ( diff == 0 ) + { + idx_azimuth = 0; + nbits_diff_azimuth = 1; + } + else if ( ABSVAL( diff ) < ISM_MAX_AZIMUTH_DIFF_IDX ) /* when diff bits >= abs bits, prefer abs */ + { + idx_azimuth = 1 << 1; + nbits_diff_azimuth = 1; + + if ( diff < 0 ) + { + idx_azimuth += 1; /* negative sign */ + diff *= -1; + } + else + { + idx_azimuth += 0; /* positive sign */ + } + + idx_azimuth = idx_azimuth << diff; + nbits_diff_azimuth++; + + /* unary coding of "diff */ + idx_azimuth += ( ( 1 << diff ) - 1 ); + nbits_diff_azimuth += diff; + + if ( nbits_diff_azimuth < ISM_AZIMUTH_NBITS - 1 ) + { + /* add stop bit - only for codewords shorter than ISM_AZIMUTH_NBITS */ + idx_azimuth = idx_azimuth << 1; + nbits_diff_azimuth++; + } + } + else + { + *flag_abs_azimuth = 1; + } + } + + /* update counter */ + if ( *flag_abs_azimuth == 0 ) + { + angle->azimuth_diff_cnt++; + angle->elevation_diff_cnt = min( angle->elevation_diff_cnt, ISM_FEC_MAX ); + } + else + { + angle->azimuth_diff_cnt = 0; + } + + /* Write azimuth */ + push_indice( hBstr, IND_ISM_AZIMUTH_DIFF_FLAG, *flag_abs_azimuth, 1 ); + + if ( *flag_abs_azimuth ) + { + push_indice( hBstr, IND_ISM_AZIMUTH, idx_azimuth, ISM_AZIMUTH_NBITS ); + } + else + { + push_indice( hBstr, IND_ISM_AZIMUTH, idx_azimuth, nbits_diff_azimuth ); + } + + /*----------------------------------------------------------------* + * Elevation index encoding + *----------------------------------------------------------------*/ + idx_elevation = idx_elevation_abs; + + nbits_diff_elevation = 0; + + *flag_abs_elevation = 0; /* differential coding by default */ + if ( angle->elevation_diff_cnt == ISM_FEC_MAX /* make differential encoding in ISM_FEC_MAX consecutive frames at maximum (in order to control the decoding in FEC) */ + || last_ism_metadata_flag == 0 /* If last frame had no metadata coded, do not use differential coding */ + ) + { + *flag_abs_elevation = 1; + } + + /* note: elevation is coded starting from the second frame only (it is meaningless in the init_frame) */ + if ( ini_frame == 0 ) + { + *flag_abs_elevation = 1; + angle->last_elevation_idx = idx_elevation_abs; + } + + diff = idx_elevation_abs - angle->last_elevation_idx; + + /* avoid absolute coding of elevation if absolute coding was already used for azimuth */ + if ( *flag_abs_azimuth == 1 ) + { + int16_t diff_orig = diff; + + *flag_abs_elevation = 0; + + + if ( diff >= 0 ) + { + diff = min( diff, ISM_MAX_ELEVATION_DIFF_IDX ); + } + else + { + diff = -1 * min( -diff, ISM_MAX_ELEVATION_DIFF_IDX ); + } + + if ( last_ism_metadata_flag == 0 || abs( diff_orig - diff ) > ISM_MAX_ELEVATION_DIFF_IDX ) + { + angle->elevation_diff_cnt = ISM_FEC_MAX - 1; + } + } + + /* try differential coding */ + if ( *flag_abs_elevation == 0 ) + { + if ( diff == 0 ) + { + idx_elevation = 0; + nbits_diff_elevation = 1; + } + else if ( ABSVAL( diff ) <= ISM_MAX_ELEVATION_DIFF_IDX ) + { + idx_elevation = 1 << 1; + nbits_diff_elevation = 1; + + if ( diff < 0 ) + { + idx_elevation += 1; /* negative sign */ + diff *= -1; + } + else + { + idx_elevation += 0; /* positive sign */ + } + + idx_elevation = idx_elevation << diff; + nbits_diff_elevation++; + + /* unary coding of "diff */ + idx_elevation += ( ( 1 << diff ) - 1 ); + nbits_diff_elevation += diff; + + if ( nbits_diff_elevation < ISM_ELEVATION_NBITS ) + { + /* add stop bit */ + idx_elevation = idx_elevation << 1; + nbits_diff_elevation++; + } + } + else + { + *flag_abs_elevation = 1; + } + } + + /* update counter */ + if ( *flag_abs_elevation == 0 ) + { + angle->elevation_diff_cnt++; + angle->elevation_diff_cnt = min( angle->elevation_diff_cnt, ISM_FEC_MAX ); + } + else + { + angle->elevation_diff_cnt = 0; + } + + /* Write elevation */ + if ( *flag_abs_azimuth == 0 ) /* do not write "flag_abs_elevation" if "flag_abs_azimuth == 1" */ + { + push_indice( hBstr, IND_ISM_ELEVATION_DIFF_FLAG, *flag_abs_elevation, 1 ); + } + + if ( *flag_abs_elevation ) + { + push_indice( hBstr, IND_ISM_ELEVATION, idx_elevation, ISM_ELEVATION_NBITS ); + } + else + { + push_indice( hBstr, IND_ISM_ELEVATION, idx_elevation, nbits_diff_elevation ); + } + + /*----------------------------------------------------------------* + * Updates + *----------------------------------------------------------------*/ + + angle->last_azimuth_idx = idx_azimuth_abs; + angle->last_elevation_idx = idx_elevation_abs; + + return; +} +#endif diff --git a/lib_enc/ivas_stat_enc.h b/lib_enc/ivas_stat_enc.h index 8949dac71ace8012f8d801361bb5579eefac3861..896dc0563b7c3137a98c11af442ff0ac982c12b3 100644 --- a/lib_enc/ivas_stat_enc.h +++ b/lib_enc/ivas_stat_enc.h @@ -1027,6 +1027,10 @@ typedef struct encoder_config_structure int16_t Opt_SC_VBR; /* flag indicating SC-VBR mode */ int16_t last_Opt_SC_VBR; /* flag indicating prev frame's SC-VBR mode */ +#ifdef TD5 + int16_t ism_extended_metadata_flag; /* flag indicating whether extended metadata encoding, including radius and orientation (yaw, pitch) */ +#endif + /* temp. development parameters */ int16_t Opt_PCA_ON; /* flag indicating PCA operation in SBA */ diff --git a/lib_enc/lib_enc.c b/lib_enc/lib_enc.c index ff63f604b694b4a05b2dc6494090b7fa63d79834..3742dbcfdcc01d239eaed8465acd513e78370f09 100755 --- a/lib_enc/lib_enc.c +++ b/lib_enc/lib_enc.c @@ -366,7 +366,12 @@ ivas_error IVAS_ENC_ConfigureForObjects( const bool max_bwidth_user, /* i : shows if bandwidth limitation was set by the user (true) or if default bandwidth was used (false) */ const IVAS_ENC_BANDWIDTH maxBandwidth, /* i : bandwidth limitation */ const IVAS_ENC_DTX_CONFIG dtxConfig, /* i : configuration of DTX, can by set to default by using IVAS_ENC_GetDefaultDtxConfig() */ - const uint16_t numObjects /* i : number of objects to be encoded */ +#ifdef TD5 + const uint16_t numObjects, /* i : number of objects to be encoded */ + const bool ism_extended_metadata /* i : Extended metadata used (true/false), where extended metadata includes radius and orientation */ +#else + const uint16_t numObjects /* i : number of objects to be encoded */ +#endif ) { Encoder_Struct *st_ivas; @@ -386,7 +391,9 @@ ivas_error IVAS_ENC_ConfigureForObjects( st_ivas->hEncoderConfig->ivas_format = ISM_FORMAT; st_ivas->hEncoderConfig->element_mode_init = IVAS_SCE; st_ivas->hEncoderConfig->nchan_inp = numObjects; - +#ifdef TD5 + st_ivas->hEncoderConfig->ism_extended_metadata_flag = ism_extended_metadata; +#endif hIvasEnc->maxBandwidthUser = max_bwidth_user; error = configureEncoder( hIvasEnc, inputFs, bitrate, maxBandwidth, dtxConfig, IVAS_ENC_GetDefaultChannelAwareConfig() ); @@ -426,7 +433,12 @@ ivas_error IVAS_ENC_FeedObjectMetadata( return IVAS_ERR_INDEX_OUT_OF_BOUNDS; } +#ifdef TD5 + error = ivas_set_ism_metadata( hIvasEnc->st_ivas->hIsmMetaData[ismIndex], metadata.azimuth, metadata.elevation, metadata.radius, metadata.yaw, metadata.pitch ); +#else error = ivas_set_ism_metadata( hIvasEnc->st_ivas->hIsmMetaData[ismIndex], metadata.azimuth, metadata.elevation ); +#endif + if ( error != IVAS_ERR_OK ) { return error; @@ -2001,6 +2013,12 @@ static ivas_error sanitizeBitrateISM( { return IVAS_ERROR( IVAS_ERR_INVALID_BITRATE, "Too low bitrate for 4 ISM specified in IVAS: %d", hEncoderConfig->ivas_total_brate ); } +#ifdef TD5 + if ( hEncoderConfig->ivas_total_brate < ISM_EXTENDED_METADATA_BRATE && hEncoderConfig->ism_extended_metadata_flag == 1 ) + { + return IVAS_ERROR( IVAS_ERR_INVALID_BITRATE, "Too low bitrate for extended metadata format specified in IVAS: %d", hEncoderConfig->ivas_total_brate ); + } +#endif return IVAS_ERR_OK; } diff --git a/lib_enc/lib_enc.h b/lib_enc/lib_enc.h index 9c16e69c75b72697d674ee7fd4f14e9e08785c21..37fd4b4deeeffe927a899fc08900998e221cb8f8 100644 --- a/lib_enc/lib_enc.h +++ b/lib_enc/lib_enc.h @@ -180,7 +180,12 @@ ivas_error IVAS_ENC_ConfigureForObjects( const bool max_bwidth_user, /* i : shows if bandwidth limitation was set by the user (true) or if default bandwidth was used (false) */ const IVAS_ENC_BANDWIDTH maxBandwidth, /* i : bandwidth limitation */ const IVAS_ENC_DTX_CONFIG dtxConfig, /* i : configuration of DTX, can by set to default by using IVAS_ENC_GetDefaultDtxConfig() */ +#ifdef TD5 + const uint16_t numObjects, /* i : number of objects to be encoded */ + const bool ism_extended_metadata /* i : Extended metadata used (true/false), where extended metadata includes radius and orientation */ +#else const uint16_t numObjects /* i : number of objects to be encoded */ +#endif ); /*! r: error code */ diff --git a/lib_rend/ivas_objectRenderer.c b/lib_rend/ivas_objectRenderer.c index 9041a016b1950b6d6801781670768db827c8d60f..9e8f1f070e41a761d4ac2c0406105afbffa3a4f7 100644 --- a/lib_rend/ivas_objectRenderer.c +++ b/lib_rend/ivas_objectRenderer.c @@ -47,6 +47,9 @@ *---------------------------------------------------------------------*/ static void TDREND_Clear_Update_flags( BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd ); +#ifdef TD5 +static void angles_to_vec( const float radius, const float azimuth, const float elevation, float *vec ); +#endif /*---------------------------------------------------------------------* * ivas_td_binaural_open_unwrap() @@ -55,11 +58,14 @@ static void TDREND_Clear_Update_flags( BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRe *---------------------------------------------------------------------*/ ivas_error ivas_td_binaural_open_unwrap( - TDREND_HRFILT_FiltSet_t **hHrtfTD, /* i/o: HR filter model (from file or NULL) */ - const int32_t output_Fs, /* i : Output sampling rate */ - const int16_t nchan_transport, /* i : Number of channels */ - const IVAS_FORMAT ivas_format, /* i : IVAS format (ISM/MC) */ - const AUDIO_CONFIG transport_config, /* i : Transport configuration */ + TDREND_HRFILT_FiltSet_t **hHrtfTD, /* i/o: HR filter model (from file or NULL) */ + const int32_t output_Fs, /* i : Output sampling rate */ + const int16_t nchan_transport, /* i : Number of channels */ + const IVAS_FORMAT ivas_format, /* i : IVAS format (ISM/MC) */ + const AUDIO_CONFIG transport_config, /* i : Transport configuration */ +#ifdef TD5 + const float *directivity, /* i : Directivity pattern (used for ISm) */ +#endif const IVAS_OUTPUT_SETUP hTransSetup, /* i : Loudspeaker layout */ BINAURAL_TD_OBJECT_RENDERER_HANDLE *hBinRendererTd, /* o : TD renderer handle */ int32_t *binaural_latency_ns /* i : Binauralization delay */ @@ -168,9 +174,13 @@ ivas_error ivas_td_binaural_open_unwrap( for ( nS = 0; nS < nchan_rend; nS++ ) { /* Set source positions according to loudspeaker layout */ +#ifdef TD5 + angles_to_vec( 1.0f, ls_azimuth[nS], ls_elevation[nS], Pos ); +#else Pos[0] = cosf( ls_elevation[nS] * PI_OVER_180 ) * cosf( ls_azimuth[nS] * PI_OVER_180 ); Pos[1] = cosf( ls_elevation[nS] * PI_OVER_180 ) * sinf( ls_azimuth[nS] * PI_OVER_180 ); Pos[2] = sinf( ls_elevation[nS] * PI_OVER_180 ); +#endif Dir[0] = 1.0f; Dir[1] = 0.0f; Dir[2] = 0.0f; @@ -186,6 +196,20 @@ ivas_error ivas_td_binaural_open_unwrap( TDREND_MIX_SRC_SetDirAtten( pBinRendTd, nS, DirAtten_p ); } } +#ifdef TD5 + if ( ivas_format == ISM_FORMAT ) + { + DirAtten_p = pBinRendTd->DirAtten_p; + DirAtten_p->ConeInnerAngle = directivity[0]; + DirAtten_p->ConeOuterAngle = directivity[1]; + DirAtten_p->ConeOuterGain = directivity[2]; + + for ( nS = 0; nS < nchan_rend; nS++ ) + { + TDREND_MIX_SRC_SetDirAtten( pBinRendTd, nS, DirAtten_p ); + } + } +#endif *hBinRendererTd = pBinRendTd; *binaural_latency_ns = (int32_t) ( ( *hBinRendererTd )->HrFiltSet_p->latency_s * 1000000000.f ); @@ -236,8 +260,11 @@ ivas_error ivas_td_binaural_renderer_unwrap( ISM_METADATA_HANDLE *hIsmMetaData, /* i : ISM metadata handle */ const int16_t Opt_Headrotation, /* i : Head rotation flag */ const IVAS_QUATERNION *Quaternions, /* i : Head tracking data per subframe */ - float output[][L_FRAME48k], /* i/o: SCE channels / Binaural synthesis */ - const int16_t output_frame /* i : output frame length */ +#ifdef TD5 + const IVAS_POSITION *Pos, /* i : Listener position data per subframe */ +#endif + float output[][L_FRAME48k], /* i/o: SCE channels / Binaural synthesis */ + const int16_t output_frame /* i : output frame length */ ) { int16_t subframe_length; @@ -253,7 +280,11 @@ ivas_error ivas_td_binaural_renderer_unwrap( for ( subframe_idx = 0; subframe_idx < MAX_PARAM_SPATIAL_SUBFRAMES; subframe_idx++ ) { /* Update the listener's location/orientation */ +#ifdef TD5 + TDREND_Update_listener_orientation( hBinRendererTd, Opt_Headrotation, ( Quaternions != NULL ) ? &Quaternions[subframe_idx] : NULL, ( Pos != NULL ) ? &Pos[subframe_idx] : NULL ); +#else TDREND_Update_listener_orientation( hBinRendererTd, Opt_Headrotation, ( Quaternions != NULL ) ? &Quaternions[subframe_idx] : NULL ); +#endif if ( ( hReverb != NULL ) && ( hReverb->pConfig.roomAcoustics.late_reverb_on ) ) { @@ -412,6 +443,10 @@ void TDREND_Update_object_positions( /* Update the source positions */ /* Source position and direction */ +#ifdef TD5 + angles_to_vec( hIsmMetaData[nS]->radius, hIsmMetaData[nS]->azimuth, hIsmMetaData[nS]->elevation, Pos ); + angles_to_vec( 1.0f, hIsmMetaData[nS]->yaw, hIsmMetaData[nS]->pitch, Dir ); +#else Pos[0] = cosf( hIsmMetaData[nS]->elevation * PI_OVER_180 ) * cosf( hIsmMetaData[nS]->azimuth * PI_OVER_180 ); Pos[1] = cosf( hIsmMetaData[nS]->elevation * PI_OVER_180 ) * sinf( hIsmMetaData[nS]->azimuth * PI_OVER_180 ); Pos[2] = sinf( hIsmMetaData[nS]->elevation * PI_OVER_180 ); @@ -423,7 +458,7 @@ void TDREND_Update_object_positions( DirAtten_p->ConeInnerAngle = 360.0f; DirAtten_p->ConeOuterAngle = 360.0f; DirAtten_p->ConeOuterGain = 1.0f; - +#endif TDREND_MIX_SRC_SetPos( hBinRendererTd, nS, Pos ); TDREND_MIX_SRC_SetDirAtten( hBinRendererTd, nS, DirAtten_p ); TDREND_MIX_SRC_SetPlayState( hBinRendererTd, nS, TDREND_PLAYSTATUS_PLAYING ); @@ -445,19 +480,29 @@ void TDREND_Update_object_positions( void TDREND_Update_listener_orientation( BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD Renderer handle */ const int16_t headRotEnabled, /* i : Headrotation flag */ - const IVAS_QUATERNION *headPosition /* i : Head Position */ +#ifdef TD5 + const IVAS_QUATERNION *headPosition, /* i : Listener orientation */ + const IVAS_POSITION *Pos /* i : Listener Position */ +#else + const IVAS_QUATERNION *headPosition /* i : Head Position */ +#endif ) { +#ifndef TD5 float Pos[3]; +#endif float FrontVec[3]; float UpVec[3]; float Rmat[3][3]; - +#ifdef TD5 + float Pos_p[3]; +#else /* Update the listener's location/orientation */ /* Listener at the origin */ Pos[0] = 0.0f; Pos[1] = 0.0f; Pos[2] = 0.0f; +#endif if ( headRotEnabled ) { @@ -471,6 +516,12 @@ void TDREND_Update_listener_orientation( UpVec[0] = Rmat[2][0]; UpVec[1] = Rmat[2][1]; UpVec[2] = Rmat[2][2]; +#ifdef TD5 + /* Input position */ + Pos_p[0] = ( *Pos ).x; + Pos_p[1] = ( *Pos ).y; + Pos_p[2] = ( *Pos ).z; +#endif } else { @@ -482,10 +533,20 @@ void TDREND_Update_listener_orientation( UpVec[0] = 0.0f; UpVec[1] = 0.0f; UpVec[2] = 1.0f; +#ifdef TD5 + /* Listener at the origin */ + Pos_p[0] = 0.0f; + Pos_p[1] = 0.0f; + Pos_p[2] = 0.0f; +#endif } /* Set the listener position and orientation:*/ +#ifdef TD5 + TDREND_MIX_LIST_SetPos( hBinRendererTd, Pos_p ); +#else TDREND_MIX_LIST_SetPos( hBinRendererTd, Pos ); +#endif TDREND_MIX_LIST_SetOrient( hBinRendererTd, FrontVec, UpVec ); return; @@ -501,6 +562,9 @@ void TDREND_Update_listener_orientation( ivas_error ivas_td_binaural_open_ext( TDREND_WRAPPER *pTDRend, IVAS_REND_AudioConfig inConfig, +#ifdef TD5 + RENDER_CONFIG_DATA *hRendCfg, /* i : Renderer configuration */ +#endif LSSETUP_CUSTOM_STRUCT *customLsInput, const int32_t outFs ) { @@ -527,7 +591,11 @@ ivas_error ivas_td_binaural_open_ext( hTransSetup.ls_azimuth = customLsInput->ls_azimuth; hTransSetup.ls_elevation = customLsInput->ls_elevation; +#ifdef TD5 + return ivas_td_binaural_open_unwrap( &pTDRend->hHrtfTD, outFs, nchan_transport, ivas_format, transport_config, hRendCfg->directivity, hTransSetup, &pTDRend->hBinRendererTd, &pTDRend->binaural_latency_ns ); +#else return ivas_td_binaural_open_unwrap( &pTDRend->hHrtfTD, outFs, nchan_transport, ivas_format, transport_config, hTransSetup, &pTDRend->hBinRendererTd, &pTDRend->binaural_latency_ns ); +#endif } @@ -589,10 +657,20 @@ ivas_error ivas_td_binaural_renderer_ext( hIsmMetaData[0] = &hIsmMetaDataFrame; hIsmMetaData[0]->azimuth = currentPos->azimuth; hIsmMetaData[0]->elevation = currentPos->elevation; +#ifdef TD5 + hIsmMetaData[0]->yaw = currentPos->yaw; + hIsmMetaData[0]->pitch = currentPos->pitch; + hIsmMetaData[0]->radius = currentPos->radius; +#endif } if ( ( error = ivas_td_binaural_renderer_unwrap( reverb, transport_config, pTDRend->hBinRendererTd, num_src, lfe_idx, ivas_format, hIsmMetaData, headRotData->headRotEnabled, - ( headRotData != NULL ) ? headRotData->headPositions : NULL, output, output_frame ) ) != IVAS_ERR_OK ) + ( headRotData != NULL ) ? headRotData->headPositions : NULL, +#ifdef TD5 + ( headRotData != NULL ) ? headRotData->Pos : NULL, output, output_frame ) ) != IVAS_ERR_OK ) +#else + output, output_frame ) ) != IVAS_ERR_OK ) +#endif { return error; } @@ -601,3 +679,25 @@ ivas_error ivas_td_binaural_renderer_ext( return IVAS_ERR_OK; } + +#ifdef TD5 +/*---------------------------------------------------------------------* + * angles_to_vec() + * + * Convert azimuth and elevation angles to position/orientation vector + *---------------------------------------------------------------------*/ + +static void angles_to_vec( + const float radius, /* i : radius */ + const float azimuth, /* i : Azimuth angle */ + const float elevation, /* i : Elevation angle */ + float *vec /* o : Pos/Dir vector */ +) +{ + vec[0] = radius * cosf( elevation * PI_OVER_180 ) * cosf( azimuth * PI_OVER_180 ); + vec[1] = radius * cosf( elevation * PI_OVER_180 ) * sinf( azimuth * PI_OVER_180 ); + vec[2] = radius * sinf( elevation * PI_OVER_180 ); + + return; +} +#endif diff --git a/lib_rend/ivas_objectRenderer_hrFilt.c b/lib_rend/ivas_objectRenderer_hrFilt.c index 0220b481450f403294a5cc453e8931780e7f5f8e..d28abdba30626bed51d1485baf0899c67c08b264 100644 --- a/lib_rend/ivas_objectRenderer_hrFilt.c +++ b/lib_rend/ivas_objectRenderer_hrFilt.c @@ -69,10 +69,21 @@ ivas_error TDREND_REND_RenderSourceHRFilt( { float LeftOutputFrame[L_SPATIAL_SUBFR_48k]; float RightOutputFrame[L_SPATIAL_SUBFR_48k]; +#ifdef TD5 + float Gain; + + Gain = ( *Src_p->SrcRend_p->DirGain_p ) * ( *Src_p->SrcRend_p->DistGain_p ); +#endif TDREND_Apply_ITD( Src_p->InputFrame_p, LeftOutputFrame, RightOutputFrame, &Src_p->previtd, Src_p->itd, Src_p->mem_itd, subframe_length ); +#ifdef TD5 + TDREND_firfilt( LeftOutputFrame, Src_p->hrf_left_prev, hrf_left_delta, intp_count, Src_p->mem_hrf_left, subframe_length, Src_p->filterlength, Gain ); + TDREND_firfilt( RightOutputFrame, Src_p->hrf_right_prev, hrf_right_delta, intp_count, Src_p->mem_hrf_right, subframe_length, Src_p->filterlength, Gain ); +#else TDREND_firfilt( LeftOutputFrame, Src_p->hrf_left_prev, hrf_left_delta, intp_count, Src_p->mem_hrf_left, subframe_length, Src_p->filterlength ); TDREND_firfilt( RightOutputFrame, Src_p->hrf_right_prev, hrf_right_delta, intp_count, Src_p->mem_hrf_right, subframe_length, Src_p->filterlength ); +#endif + /* Copy to accumulative output frame */ v_add( LeftOutputFrame, output_buf[0], output_buf[0], subframe_length ); v_add( RightOutputFrame, output_buf[1], output_buf[1], subframe_length ); diff --git a/lib_rend/ivas_objectRenderer_sfx.c b/lib_rend/ivas_objectRenderer_sfx.c index 005025827b8cc0c49158fb6fd7a83b11c86facf8..42a3b8cbcaab19394f90d2b9e90c403a3529fe6c 100644 --- a/lib_rend/ivas_objectRenderer_sfx.c +++ b/lib_rend/ivas_objectRenderer_sfx.c @@ -234,7 +234,12 @@ void TDREND_firfilt( const int16_t intp_count, /* i : interpolation count */ float *mem, /* i/o: filter memory */ const int16_t subframe_length, /* i : Length of signal */ - const int16_t filterlength /* i : Filter length */ +#ifdef TD5 + const int16_t filterlength, /* i : Filter length */ + const float Gain /* i : Gain */ +#else + const int16_t filterlength /* i : Filter length */ +#endif ) { float buffer[SFX_SPAT_BIN_MAX_FILTER_LENGTH - 1 + L_SUBFRAME5MS_48k]; @@ -260,7 +265,11 @@ void TDREND_firfilt( { tmp += ( *p_filter++ ) * ( *p_tmp-- ); } +#ifdef TD5 + signal[i] = tmp * Gain; +#else signal[i] = tmp; +#endif if ( i < intp_count ) { diff --git a/lib_rend/ivas_objectRenderer_sources.c b/lib_rend/ivas_objectRenderer_sources.c index d52422881292a65957e4c2d0c9d99a38f0d6ea7b..2a13efc24c219dec2e8d608a01e71498df33fee3 100644 --- a/lib_rend/ivas_objectRenderer_sources.c +++ b/lib_rend/ivas_objectRenderer_sources.c @@ -266,6 +266,9 @@ void TDREND_SRC_REND_UpdateFiltersFromSpatialParams( TDREND_MIX_Listener_t *Listener_p; TDREND_HRFILT_FiltSet_t *HrFiltSet_p; float ListRelPos[3], ListRelDist; +#ifdef TD5 + float ListRelPosAbs[3]; /* Relative position, ignoring orientation of listener */ +#endif float Azim, Elev; float hrf_left[SFX_SPAT_BIN_MAX_FILTER_LENGTH]; float hrf_right[SFX_SPAT_BIN_MAX_FILTER_LENGTH]; @@ -287,14 +290,22 @@ void TDREND_SRC_REND_UpdateFiltersFromSpatialParams( break; case TDREND_POSTYPE_ABSOLUTE: /* Absolute position */ +#ifdef TD5 + TDREND_SPATIAL_VecMapToNewCoordSystem( SrcSpatial_p->Pos_p, Listener_p->Pos, Listener_p->Front, Listener_p->Up, Listener_p->Right, ListRelPos, ListRelPosAbs ); +#else TDREND_SPATIAL_VecMapToNewCoordSystem( SrcSpatial_p->Pos_p, Listener_p->Pos, Listener_p->Front, Listener_p->Up, Listener_p->Right, ListRelPos ); +#endif break; default: /* Illegal position type */ #ifdef DEBUGGING printf( "Warning! TDREND_SRC_REND_UpdateFiltersFromSpatialParams: Invalid position type. Assuming absolute position!\n" ); #endif /* Assume absolute position */ +#ifdef TD5 + TDREND_SPATIAL_VecMapToNewCoordSystem( SrcSpatial_p->Pos_p, Listener_p->Pos, Listener_p->Front, Listener_p->Up, Listener_p->Right, ListRelPos, ListRelPosAbs ); +#else TDREND_SPATIAL_VecMapToNewCoordSystem( SrcSpatial_p->Pos_p, Listener_p->Pos, Listener_p->Front, Listener_p->Up, Listener_p->Right, ListRelPos ); +#endif break; } @@ -320,7 +331,11 @@ void TDREND_SRC_REND_UpdateFiltersFromSpatialParams( *SrcRend_p->DirGain_p = 1.0f; if ( SrcSpatial_p->DirAttenEnabled ) { +#ifdef TD5 + *SrcRend_p->DirGain_p = TDREND_SRC_SPATIAL_GetDirGain( &SrcSpatial_p->DirAtten, SrcSpatial_p->Front_p, ListRelPosAbs ); +#else *SrcRend_p->DirGain_p = TDREND_SRC_SPATIAL_GetDirGain( &SrcSpatial_p->DirAtten, SrcSpatial_p->Front_p, ListRelPos ); +#endif } /* Distance gain */ diff --git a/lib_rend/ivas_objectRenderer_vec.c b/lib_rend/ivas_objectRenderer_vec.c index c3a780c725fa66aa07fe592adfb06dba643098b8..f17d769821ab9e3abee43fed7b53d02829a14dfd 100644 --- a/lib_rend/ivas_objectRenderer_vec.c +++ b/lib_rend/ivas_objectRenderer_vec.c @@ -111,9 +111,22 @@ void TDREND_SPATIAL_VecMapToNewCoordSystem( const float *DirVec_p, /* i : Direction vector */ const float *UpVec_p, /* i : Up vector */ const float *RightVec_p, /* i : Right vector */ - float *MappedVec_p /* o : Transformed vector */ +#ifdef TD5 + float *MappedVec_p, /* o : Transformed vector */ + float *LisRelPosAbs /* o : Transformed vector ignoring orientation */ +#else + float *MappedVec_p /* o : Transformed vector */ +#endif ) { +#ifdef TD5 + v_sub( Vec_p, TranslVec_p, LisRelPosAbs, 3 ); + /* Evalute the relative Vec in the coordinates of the Orientation vectors, */ + /* which form an orthonormal basis */ + MappedVec_p[0] = dotp( LisRelPosAbs, DirVec_p, 3 ); + MappedVec_p[1] = dotp( LisRelPosAbs, RightVec_p, 3 ); + MappedVec_p[2] = dotp( LisRelPosAbs, UpVec_p, 3 ); +#else float RelVec[3]; /* Evaluate Vec relative to the new origin given by TranslVec */ @@ -124,7 +137,7 @@ void TDREND_SPATIAL_VecMapToNewCoordSystem( MappedVec_p[0] = dotp( RelVec, DirVec_p, 3 ); MappedVec_p[1] = dotp( RelVec, RightVec_p, 3 ); MappedVec_p[2] = dotp( RelVec, UpVec_p, 3 ); - +#endif return; } diff --git a/lib_rend/ivas_prot_rend.h b/lib_rend/ivas_prot_rend.h index ea3db3225940ad67b9f8c5f80cd8108298578bc2..5911112015a5bcb466e5ae8b1c38667200c647c7 100644 --- a/lib_rend/ivas_prot_rend.h +++ b/lib_rend/ivas_prot_rend.h @@ -221,6 +221,9 @@ ivas_error ivas_td_binaural_renderer_unwrap( ISM_METADATA_HANDLE *hIsmMetaData, /* i : ISM metadata handle */ const int16_t Opt_Headrotation, /* i : Head rotation flag */ const IVAS_QUATERNION *Quaternions, /* i : Head tracking data per subframe */ +#ifdef TD5 + const IVAS_POSITION *Pos, /* i : Listener position data per subframe */ +#endif float output[][L_FRAME48k], /* i/o: SCE channels / Binaural synthesis */ const int16_t output_frame /* i : output frame length */ ); @@ -242,6 +245,9 @@ ivas_error ivas_td_binaural_open_unwrap( const int16_t nchan_transport, /* i : Number of channels */ const IVAS_FORMAT ivas_format, /* i : IVAS format (ISM/MC) */ const AUDIO_CONFIG transport_config, /* i : Transport configuration */ +#ifdef TD5 + const float *directivity, /* i : Directivity pattern (used for ISm) */ +#endif const IVAS_OUTPUT_SETUP hTransSetup, /* i : Loudspeaker layout */ BINAURAL_TD_OBJECT_RENDERER_HANDLE *hBinRendererTd, /* o : TD renderer handle */ int32_t *binaural_latency_ns /* i : Binauralization delay */ @@ -250,6 +256,9 @@ ivas_error ivas_td_binaural_open_unwrap( ivas_error ivas_td_binaural_open_ext( TDREND_WRAPPER *pTDRend, const IVAS_REND_AudioConfig inConfig, +#ifdef TD5 + RENDER_CONFIG_DATA *hRendCfg, /* i : Renderer configuration */ +#endif LSSETUP_CUSTOM_STRUCT *customLsInput, const int32_t output_Fs ); @@ -269,7 +278,12 @@ ivas_error TDREND_GetMix( void TDREND_Update_listener_orientation( BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD Renderer handle */ const int16_t headRotEnabled, /* i : Headrotation flag */ +#ifdef TD5 + const IVAS_QUATERNION *headPosition, /* i : Listener orientation */ + const IVAS_POSITION *Pos /* i : Listener Position */ +#else const IVAS_QUATERNION *headPosition /* i : Head Position */ +#endif ); void TDREND_Update_object_positions( @@ -390,7 +404,12 @@ void TDREND_SPATIAL_VecMapToNewCoordSystem( const float *DirVec_p, /* i : Direction vector */ const float *UpVec_p, /* i : Up vector */ const float *RightVec_p, /* i : Right vector */ +#ifdef TD5 + float *MappedVec_p, /* o : Transformed vector */ + float *LisRelPosAbs /* o : Transformed vector ignoring orientation */ +#else float *MappedVec_p /* o : Transformed vector */ +#endif ); /*! r: Flag if the orientation has been updated */ @@ -456,7 +475,12 @@ void TDREND_firfilt( const int16_t intp_count, /* i : interpolation count */ float *mem, /* i/o: filter memory */ const int16_t subframe_length, /* i : Length of signal */ +#ifdef TD5 + const int16_t filterlength, /* i : Filter length */ + const float Gain /* i : Gain */ +#else const int16_t filterlength /* i : Filter length */ +#endif ); diff --git a/lib_rend/ivas_render_config.c b/lib_rend/ivas_render_config.c index ccee4ffe724264ba1e4ef2150797b1bb634fe6b1..2fdbeff0eb1840ecd60eb4d579c4baecb3097cfe 100644 --- a/lib_rend/ivas_render_config.c +++ b/lib_rend/ivas_render_config.c @@ -103,6 +103,7 @@ ivas_error ivas_render_config_init_from_rom( const int16_t room_flag_on /* i : room effect on/off flag */ ) { + if ( hRenderConfig == NULL || *hRenderConfig == NULL ) { return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "Unexpected null pointer while attempting to fill renderer configuration from ROM" ); @@ -125,5 +126,11 @@ ivas_error ivas_render_config_init_from_rom( mvr2r( ivas_reverb_default_RT60, ( *hRenderConfig )->roomAcoustics.pAcoustic_rt60, IVAS_REVERB_DEFAULT_N_BANDS ); mvr2r( ivas_reverb_default_DSR, ( *hRenderConfig )->roomAcoustics.pAcoustic_dsr, IVAS_REVERB_DEFAULT_N_BANDS ); +#ifdef TD5 + ( *hRenderConfig )->directivity[0] = 360.0f; /* Front cone */ + ( *hRenderConfig )->directivity[1] = 360.0f; /* Back cone */ + ( *hRenderConfig )->directivity[2] = 1.0f; /* Back attenuation */ +#endif + return IVAS_ERR_OK; } diff --git a/lib_rend/ivas_stat_rend.h b/lib_rend/ivas_stat_rend.h index 586a43c4f8af75aad98de0c9f472aeb39ec2ced4..05959ce73dbe726836ebbeef4741a8c59721e2cb 100644 --- a/lib_rend/ivas_stat_rend.h +++ b/lib_rend/ivas_stat_rend.h @@ -230,6 +230,9 @@ typedef struct { int8_t headRotEnabled; IVAS_QUATERNION headPositions[RENDERER_HEAD_POSITIONS_PER_FRAME]; +#ifdef TD5 + IVAS_POSITION Pos[RENDERER_HEAD_POSITIONS_PER_FRAME]; +#endif float crossfade[L_FRAME48k / RENDERER_HEAD_POSITIONS_PER_FRAME]; } IVAS_REND_HeadRotData; @@ -238,6 +241,9 @@ typedef struct ivas_binaural_head_track_struct { int16_t num_quaternions; IVAS_QUATERNION Quaternions[MAX_PARAM_SPATIAL_SUBFRAMES]; +#ifdef TD5 + IVAS_POSITION Pos[MAX_PARAM_SPATIAL_SUBFRAMES]; +#endif float Rmat[3][3]; float Rmat_prev[3][3]; @@ -306,7 +312,9 @@ typedef struct ivas_render_config_t ivas_renderTypeOverride renderer_type_override; #endif ivas_roomAcoustics_t roomAcoustics; - +#ifdef TD5 + float directivity[3]; +#endif } RENDER_CONFIG_DATA, *RENDER_CONFIG_HANDLE; typedef struct ivas_rev_delay_line_t diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 8ad381584ba0cb680895a672e2fab62340ed5758..919d6ee968350fe35dece15eb646e4fddbe166b7 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -985,6 +985,11 @@ static IVAS_REND_AudioObjectPosition defaultObjectPosition( pos.azimuth = 0.0f; pos.elevation = 0.0f; +#ifdef TD5 + pos.radius = 1.0f; + pos.yaw = 0.0f; + pos.pitch = 0.0f; +#endif return pos; } @@ -1075,7 +1080,11 @@ static ivas_error setRendInputActiveIsm( error = IVAS_ERR_OK; if ( outConfig == IVAS_REND_AUDIO_CONFIG_BINAURAL ) { +#ifdef TD5 + if ( ( error = ivas_td_binaural_open_ext( &inputIsm->tdRendWrapper, inConfig, hRendCfg, NULL, *rendCtx.pOutSampleRate ) ) != IVAS_ERR_OK ) +#else if ( ( error = ivas_td_binaural_open_ext( &inputIsm->tdRendWrapper, inConfig, NULL, *rendCtx.pOutSampleRate ) ) != IVAS_ERR_OK ) +#endif { return error; } @@ -1084,7 +1093,11 @@ static ivas_error setRendInputActiveIsm( { if ( hRendCfg != NULL && hRendCfg->roomAcoustics.use_brir == 0 && hRendCfg->roomAcoustics.late_reverb_on ) { +#ifdef TD5 + if ( ( error = ivas_td_binaural_open_ext( &inputIsm->tdRendWrapper, inConfig, hRendCfg, NULL, *rendCtx.pOutSampleRate ) ) != IVAS_ERR_OK ) +#else if ( ( error = ivas_td_binaural_open_ext( &inputIsm->tdRendWrapper, inConfig, NULL, *rendCtx.pOutSampleRate ) ) != IVAS_ERR_OK ) +#endif { return error; } @@ -1802,7 +1815,11 @@ static ivas_error initMcBinauralRendering( // if ( initTDRend ) { +#ifdef TD5 + if ( ( error = ivas_td_binaural_open_ext( &inputMc->tdRendWrapper, inConfig, hRendCfg, &inputMc->customLsInput, outSampleRate ) ) != IVAS_ERR_OK ) +#else if ( ( error = ivas_td_binaural_open_ext( &inputMc->tdRendWrapper, inConfig, &inputMc->customLsInput, outSampleRate ) ) != IVAS_ERR_OK ) +#endif { return error; } @@ -3789,6 +3806,9 @@ int16_t IVAS_REND_FeedRenderConfig( } hRenderConfig = hIvasRend->hRendererConfig; +#ifdef TD5 + mvr2r( renderConfig.directivity, hRenderConfig->directivity, 3 ); +#endif #ifdef DEBUGGING hRenderConfig->renderer_type_override = RENDER_TYPE_OVERRIDE_NONE; if ( renderConfig.renderer_type_override == IVAS_RENDER_TYPE_OVERRIDE_FASTCONV ) @@ -3821,8 +3841,13 @@ int16_t IVAS_REND_FeedRenderConfig( *-------------------------------------------------------------------*/ ivas_error IVAS_REND_SetHeadRotation( - IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ +#ifdef TD5 + const IVAS_QUATERNION headRot[RENDERER_HEAD_POSITIONS_PER_FRAME], /* i : head orientations for next rendering call */ + const IVAS_POSITION Pos[RENDERER_HEAD_POSITIONS_PER_FRAME] /* i : listener positions for next rendering call */ +#else const IVAS_QUATERNION headRot[RENDERER_HEAD_POSITIONS_PER_FRAME] /* i : head positions for next rendering call */ +#endif ) { int16_t i; @@ -3852,6 +3877,9 @@ ivas_error IVAS_REND_SetHeadRotation( for ( i = 0; i < RENDERER_HEAD_POSITIONS_PER_FRAME; ++i ) { hIvasRend->headRotData.headPositions[i] = headRot[i]; +#ifdef TD5 + hIvasRend->headRotData.Pos[i] = Pos[i]; +#endif } } diff --git a/lib_rend/lib_rend.h b/lib_rend/lib_rend.h index 6db5fd91dc12c7a4cecb82d801a1f5c50ba6adb1..579dda711f8e3a47b58a1fcdfd684c91a06777b1 100644 --- a/lib_rend/lib_rend.h +++ b/lib_rend/lib_rend.h @@ -244,7 +244,12 @@ int16_t IVAS_REND_FeedRenderConfig( ivas_error IVAS_REND_SetHeadRotation( IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ +#ifdef TD5 + const IVAS_QUATERNION headRot[RENDERER_HEAD_POSITIONS_PER_FRAME], /* i : head orientations for next rendering call */ + const IVAS_POSITION Pos[RENDERER_HEAD_POSITIONS_PER_FRAME] /* i : listener positions for next rendering call */ +#else const IVAS_QUATERNION headRot[RENDERER_HEAD_POSITIONS_PER_FRAME] /* i : head positions for next rendering call */ +#endif ); ivas_error IVAS_REND_GetSamples( diff --git a/lib_util/head_rotation_file_reader.c b/lib_util/head_rotation_file_reader.c index 533c14a6515edce05db918749c2d79749812920b..d3a1018644ee0bb97db34640b7aafee939f818e1 100644 --- a/lib_util/head_rotation_file_reader.c +++ b/lib_util/head_rotation_file_reader.c @@ -93,33 +93,58 @@ ivas_error HeadRotationFileReader_open( ivas_error HeadRotationFileReading( HeadRotFileReader *headRotReader, /* i/o: HeadRotFileReader handle */ - IVAS_QUATERNION *Quaternions, /* o : head-tracking data */ - const int32_t frame_dec /* i : decoded frame number */ + IVAS_QUATERNION *Quaternions, /* o : head-tracking data, listener orientation */ +#ifdef TD5 + IVAS_POSITION *Pos /* o : listener position */ +#else + const int32_t frame_dec /* i : decoded frame number */ +#endif ) { uint16_t i; float w, x, y, z; +#ifdef TD5 + float posx, posy, posz; + int32_t read_values; + + posx = 0.0f; + posy = 0.0f; + posz = 0.0f; +#endif for ( i = 0; i < IVAS_MAX_PARAM_SPATIAL_SUBFRAMES; i++ ) { +#ifdef TD5 + read_values = fscanf( headRotReader->trajFile, "%f,%f,%f,%f,%f,%f,%f", &w, &x, &y, &z, &posx, &posy, &posz ); + if ( ( read_values != 4 ) && ( read_values != 7 ) ) /* Allow either orientation (4) or orientation+position (4+3) */ +#else if ( 4 != fscanf( headRotReader->trajFile, "%f,%f,%f,%f", &w, &x, &y, &z ) ) +#endif { if ( feof( headRotReader->trajFile ) ) { rewind( headRotReader->trajFile ); headRotReader->fileRewind = true; +#ifdef TD5 + return HeadRotationFileReading( headRotReader, Quaternions, Pos ); +#else return HeadRotationFileReading( headRotReader, Quaternions, frame_dec ); +#endif } return IVAS_ERR_FAILED_FILE_PARSE; } - ( headRotReader->frameCounter )++; Quaternions[i].w = w; Quaternions[i].x = x; Quaternions[i].y = y; Quaternions[i].z = z; +#ifdef TD5 + Pos[i].x = posx; + Pos[i].y = posy; + Pos[i].z = posz; +#endif } return IVAS_ERR_OK; diff --git a/lib_util/head_rotation_file_reader.h b/lib_util/head_rotation_file_reader.h index e70281401af40b5f00e246f40989be91ecaa5d9d..6fa05caef1df16131adf4c393d582ddf696aea2b 100644 --- a/lib_util/head_rotation_file_reader.h +++ b/lib_util/head_rotation_file_reader.h @@ -60,7 +60,11 @@ ivas_error HeadRotationFileReader_open( ivas_error HeadRotationFileReading( HeadRotFileReader *headRotReader, /* i/o: HeadRotFileReader handle */ IVAS_QUATERNION *Quaternions, /* o : head-tracking data */ - const int32_t frame_dec /* i : decoded frame number */ +#ifdef TD5 + IVAS_POSITION *Pos /* o : listener position */ +#else + const int32_t frame_dec /* i : decoded frame number */ +#endif ); /*-----------------------------------------------------------------------* diff --git a/lib_util/ism_file_reader.c b/lib_util/ism_file_reader.c index 77912f5c586251110a57d708b529499f483aecd9..b6166af95bd3fab2e471bec982ef9cc02c010d80 100644 --- a/lib_util/ism_file_reader.c +++ b/lib_util/ism_file_reader.c @@ -36,8 +36,13 @@ #include -#define META_LINE_LENGTH 200 /* max number of characters at one line of metadata input/output file */ -#define NUM_ISM_METADATA_PER_LINE 5 /* Number of ISM metadata per line in a metadata file */ +#define META_LINE_LENGTH 200 /* max number of characters at one line of metadata input/output file */ +#ifdef TD5 +#define NUM_ISM_METADATA_PER_LINE 7 /* Number of ISM metadata per line in a metadata file */ +#define NUM_MIN_ISM_METADATA 2 /* Minimum number of metadata parameters (azimuth and elevation) */ +#else +#define NUM_ISM_METADATA_PER_LINE 5 /* Number of ISM metadata per line in a metadata file */ +#endif struct IsmFileReader @@ -95,10 +100,21 @@ ivas_error IsmFileReader_readNextFrame( { char char_buff[META_LINE_LENGTH]; float meta_prm[NUM_ISM_METADATA_PER_LINE]; +#ifdef TD5 + float meta_prm_default[NUM_ISM_METADATA_PER_LINE] = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f }; +#endif char *char_ptr; int16_t i; FILE *file; +#ifdef TD5 + /* Set default metadata parameters */ + for ( i = 0; i < NUM_ISM_METADATA_PER_LINE; i++ ) + { + meta_prm[i] = meta_prm_default[i]; + } +#endif + if ( ismMetadata == NULL || self->file == NULL ) { return IVAS_ERR_UNEXPECTED_NULL_POINTER; @@ -127,24 +143,34 @@ ivas_error IsmFileReader_readNextFrame( meta_prm[i++] = (float) atof( char_ptr ); } - +#ifdef TD5 + /* Check if minimum number of metadata values were read. Additional values are ignored. */ + if ( i < NUM_MIN_ISM_METADATA ) +#else if ( i != NUM_ISM_METADATA_PER_LINE ) +#endif { /* Not enough values provided in one line */ return IVAS_ERR_ISM_FILE_READER_INVALID_METADATA_FORMAT; } +#ifndef TD5 if ( char_ptr != NULL ) { /* Too many values provided in one line */ return IVAS_ERR_ISM_FILE_READER_INVALID_METADATA_FORMAT; } +#endif ismMetadata->azimuth = meta_prm[0]; ismMetadata->elevation = meta_prm[1]; ismMetadata->radius = meta_prm[2]; ismMetadata->spread = meta_prm[3]; ismMetadata->gainFactor = meta_prm[4]; +#ifdef TD5 + ismMetadata->yaw = meta_prm[5]; + ismMetadata->pitch = meta_prm[6]; +#endif /* verify whether the read metadata values are in an expected range */ if ( ismMetadata->azimuth > 180 || ismMetadata->azimuth < -180 ) @@ -171,6 +197,17 @@ ivas_error IsmFileReader_readNextFrame( { return IVAS_ERR_ISM_INVALID_METADATA_VALUE; } +#ifdef TD5 + if ( ismMetadata->yaw > 180 || ismMetadata->yaw < -180 ) + { + return IVAS_ERR_ISM_INVALID_METADATA_VALUE; + } + + if ( ismMetadata->pitch > 90 || ismMetadata->pitch < -90 ) + { + return IVAS_ERR_ISM_INVALID_METADATA_VALUE; + } +#endif return IVAS_ERR_OK; } diff --git a/lib_util/ism_file_writer.c b/lib_util/ism_file_writer.c index c4dffe38b03462337e460558d84449f53977aebc..7c9227a65ce1b56821ff24e9a0cf7f426e02b7a1 100644 --- a/lib_util/ism_file_writer.c +++ b/lib_util/ism_file_writer.c @@ -35,8 +35,10 @@ #include -#define META_LINE_LENGTH 200 /* max number of characters at one line of metadata input/output file */ -#define NUM_ISM_METADATA_PER_LINE 5 /* Number of ISM metadata per line in a metadata file */ +#define META_LINE_LENGTH 200 /* max number of characters at one line of metadata input/output file */ +#ifndef TD5 +#define NUM_ISM_METADATA_PER_LINE 5 /* Number of ISM metadata per line in a metadata file */ +#endif struct IsmFileWriter @@ -115,7 +117,18 @@ ivas_error IsmFileWriter_writeFrame( file = ismWriter->file; /* IVAS_fmToDo: work in progress; currently position_azimuth, position_elevation, position_radius, spread, gain_factor */ +#ifdef FIX_293_EXT_RENDERER_CLI +#ifdef TD5 + sprintf( char_buff, "%+07.2f,%+06.2f,%05.2f,%06.2f,%04.2f,%+07.2f,%+06.2f\n", ismMetadata.azimuth, ismMetadata.elevation, ismMetadata.radius, ismMetadata.spread, ismMetadata.gainFactor, ismMetadata.yaw, ismMetadata.pitch ); +#else + sprintf( char_buff, "%+07.2f,%+06.2f,%05.2f,%06.2f,%04.2f\n", ismMetadata.azimuth, ismMetadata.elevation, ismMetadata.radius, ismMetadata.spread, ismMetadata.gainFactor ); +#endif +#endif +#ifdef TD5 + snprintf( char_buff, sizeof( char_buff ), "%+07.2f,%+06.2f,%05.2f,%06.2f,%04.2f,%+07.2f,%+06.2f\n", ismMetadata.azimuth, ismMetadata.elevation, ismMetadata.radius, ismMetadata.spread, ismMetadata.gainFactor, ismMetadata.yaw, ismMetadata.pitch ); +#else snprintf( char_buff, sizeof( char_buff ), "%+07.2f,%+06.2f,%05.2f,%06.2f,%04.2f\n", ismMetadata.azimuth, ismMetadata.elevation, ismMetadata.radius, ismMetadata.spread, ismMetadata.gainFactor ); +#endif if ( file ) { diff --git a/lib_util/render_config_reader.c b/lib_util/render_config_reader.c index 9fe7f019ebb767c5dfe384ab94eaf142fb47fe4a..907d148a6e7523172e6e2e8aa28f287abf357d75 100644 --- a/lib_util/render_config_reader.c +++ b/lib_util/render_config_reader.c @@ -522,6 +522,15 @@ ivas_error RenderConfigReader_read( errorHandler( pValue, ERROR_VALUE_INVALID ); } } +#ifdef TD5 + else if ( strcmp( item, "DIRECTIVITY" ) == 0 ) + { + if ( read_vector( pValue, 3, hRenderConfig->directivity ) ) + { + errorHandler( item, ERROR_VALUE_INVALID ); + } + } +#endif #ifdef DEBUGGING else {