diff --git a/Workspace_msvc/lib_util.vcxproj b/Workspace_msvc/lib_util.vcxproj
index 72ff2dfe6182abfbe7d1a6783c324a3958d398a6..9c68dbb36d26bb969bf1f470c4b4d85d104e7876 100644
--- a/Workspace_msvc/lib_util.vcxproj
+++ b/Workspace_msvc/lib_util.vcxproj
@@ -157,6 +157,7 @@
+
@@ -181,6 +182,7 @@
+
diff --git a/apps/decoder.c b/apps/decoder.c
index f1787da629d5f14a58460b901f5c5caa660f720c..da56077639d920f5aa486fd382dd6b89bb78d447 100644
--- a/apps/decoder.c
+++ b/apps/decoder.c
@@ -41,7 +41,11 @@
#include "ism_file_writer.h"
#include "ls_custom_file_reader.h"
#include "hrtf_file_reader.h"
+#ifdef EXTERNAL_ORIENTATIONS
+#include "rotation_file_reader.h"
+#else
#include "head_rotation_file_reader.h"
+#endif
#include "vector3_pair_file_reader.h"
#include "jbm_file_writer.h"
#include "evs_rtp_payload.h"
@@ -100,6 +104,10 @@ typedef struct
char *refrotTrajFileName;
bool enableReferenceVectorTracking;
char *referenceVectorTrajFileName;
+#ifdef EXTERNAL_ORIENTATIONS
+ bool enableExternalOrientation;
+ char *externalOrientationTrajFileName;
+#endif
#ifdef SUPPORT_JBM_TRACEFILE
char *jbmTraceFilename;
#endif
@@ -148,12 +156,20 @@ typedef struct
static bool parseCmdlIVAS_dec( int16_t argc, char **argv, DecArguments *arg );
static void usage_dec( void );
+#ifdef EXTERNAL_ORIENTATIONS
+static ivas_error decodeG192( DecArguments arg, BS_READER_HANDLE hBsReader, RotFileReader *headRotReader, RotFileReader *externalOrientationFileReader, RotFileReader *refRotReader, Vector3PairFileReader *referenceVectorReader, IVAS_DEC_HANDLE hIvasDec, int16_t *pcmBuf );
+#else
static ivas_error decodeG192( DecArguments arg, BS_READER_HANDLE hBsReader, HeadRotFileReader *headRotReader, HeadRotFileReader *refRotReader, Vector3PairFileReader *referenceVectorReader, IVAS_DEC_HANDLE hIvasDec, int16_t *pcmBuf );
+#endif
static ivas_error decodeVoIP( DecArguments arg, BS_READER_HANDLE hBsReader, IVAS_DEC_HANDLE hIvasDec );
#ifdef DEBUGGING
#ifdef VARIABLE_SPEED_DECODING
+#ifdef EXTERNAL_ORIENTATIONS
+static ivas_error decodeVariableSpeed( DecArguments arg, BS_READER_HANDLE hBsReader, RotFileReader *headRotReader, RotFileReader *externalOrientationFileReader, RotFileReader *refRotReader, Vector3PairFileReader *referenceVectorReader, IVAS_DEC_HANDLE hIvasDec );
+#else
static ivas_error decodeVariableSpeed( DecArguments arg, BS_READER_HANDLE hBsReader, HeadRotFileReader *headRotReader, HeadRotFileReader *refRotReader, Vector3PairFileReader *referenceVectorReader, IVAS_DEC_HANDLE hIvasDec );
#endif
+#endif
static ivas_error printBitstreamInfoVoip( DecArguments arg, BS_READER_HANDLE hBsReader, IVAS_DEC_HANDLE hIvasDec );
static int16_t app_own_random( int16_t *seed );
static IVAS_DEC_FORCED_REND_MODE parseForcedRendModeDec( char *forcedRendModeChar );
@@ -176,8 +192,14 @@ int main(
BS_READER_HANDLE hBsReader = NULL;
LsCustomFileReader *hLsCustomReader = NULL;
hrtfFileReader *hrtfReader = NULL;
+#ifdef EXTERNAL_ORIENTATIONS
+ RotFileReader *headRotReader = NULL;
+ RotFileReader *externalOrientationFileReader = NULL;
+ RotFileReader *refRotReader = NULL;
+#else
HeadRotFileReader *headRotReader = NULL;
HeadRotFileReader *refRotReader = NULL;
+#endif
Vector3PairFileReader *referenceVectorReader = NULL;
ivas_error error = IVAS_ERR_UNKNOWN;
int16_t pcmBuf[MAX_OUTPUT_PCM_BUFFER_SIZE];
@@ -281,7 +303,11 @@ int main(
goto cleanup;
}
+#ifdef EXTERNAL_ORIENTATIONS
+ if ( ( error = RotationFileReader_open( arg.headrotTrajFileName, &headRotReader ) ) != IVAS_ERR_OK )
+#else
if ( ( error = HeadRotationFileReader_open( arg.headrotTrajFileName, &headRotReader ) ) != IVAS_ERR_OK )
+#endif
{
fprintf( stderr, "\nError: Can't open head-rotation file %s \n\n", arg.headrotTrajFileName );
goto cleanup;
@@ -308,7 +334,11 @@ int main(
goto cleanup;
}
+#ifdef EXTERNAL_ORIENTATIONS
+ if ( ( error = RotationFileReader_open( arg.refrotTrajFileName, &refRotReader ) ) != IVAS_ERR_OK )
+#else
if ( ( error = HeadRotationFileReader_open( arg.refrotTrajFileName, &refRotReader ) ) != IVAS_ERR_OK )
+#endif
{
fprintf( stderr, "\nError: Can't open reference rotation file %s \n\n", arg.refrotTrajFileName );
goto cleanup;
@@ -342,6 +372,21 @@ int main(
}
}
+#ifdef EXTERNAL_ORIENTATIONS
+ /*------------------------------------------------------------------------------------------*
+ * Open external orientation file
+ *------------------------------------------------------------------------------------------*/
+
+ if ( arg.enableExternalOrientation )
+ {
+ if ( ( error = RotationFileReader_open( arg.externalOrientationTrajFileName, &externalOrientationFileReader ) ) != IVAS_ERR_OK )
+ {
+ fprintf( stderr, "\nError: Can't open external orientation file %s \n\n", arg.externalOrientationTrajFileName );
+ goto cleanup;
+ }
+ }
+#endif
+
/*------------------------------------------------------------------------------------------*
* Open custom loudspeaker layout file
*------------------------------------------------------------------------------------------*/
@@ -378,7 +423,11 @@ int main(
/*------------------------------------------------------------------------------------------*
* Configure the decoder
*------------------------------------------------------------------------------------------*/
+#ifdef EXTERNAL_ORIENTATIONS
+ if ( ( error = IVAS_DEC_Configure( hIvasDec, arg.output_Fs, arg.outputFormat, arg.customLsOutputEnabled, arg.hrtfReaderEnabled, arg.enableHeadRotation, arg.enableExternalOrientation, arg.orientation_tracking, arg.renderConfigEnabled, arg.Opt_non_diegetic_pan, arg.non_diegetic_pan_gain, arg.delayCompensationEnabled ) ) != IVAS_ERR_OK )
+#else
if ( ( error = IVAS_DEC_Configure( hIvasDec, arg.output_Fs, arg.outputFormat, arg.customLsOutputEnabled, arg.hrtfReaderEnabled, arg.enableHeadRotation, arg.orientation_tracking, arg.renderConfigEnabled, arg.Opt_non_diegetic_pan, arg.non_diegetic_pan_gain, arg.delayCompensationEnabled ) ) != IVAS_ERR_OK )
+#endif
{
fprintf( stderr, "\nConfigure failed: %s\n\n", IVAS_DEC_GetErrorMessage( error ) );
@@ -642,13 +691,21 @@ int main(
#ifdef DEBUGGING
else if ( arg.variableSpeedMode )
{
- error = decodeVariableSpeed( arg, hBsReader, headRotReader, refRotReader, referenceVectorReader, hIvasDec );
+ error = decodeVariableSpeed( arg, hBsReader, headRotReader,
+#ifdef EXTERNAL_ORIENTATIONS
+ externalOrientationFileReader,
+#endif
+ refRotReader, referenceVectorReader, hIvasDec );
}
#endif
#endif
else
{
- error = decodeG192( arg, hBsReader, headRotReader, refRotReader, referenceVectorReader, hIvasDec, pcmBuf );
+ error = decodeG192( arg, hBsReader, headRotReader,
+#ifdef EXTERNAL_ORIENTATIONS
+ externalOrientationFileReader,
+#endif
+ refRotReader, referenceVectorReader, hIvasDec, pcmBuf );
}
if ( error == IVAS_ERR_OK || error == IVAS_ERR_END_OF_FILE )
@@ -711,8 +768,14 @@ cleanup:
IVAS_DEC_Close( &hIvasDec );
CustomLsReader_close( &hLsCustomReader );
hrtfFileReader_close( &hrtfReader );
+#ifdef EXTERNAL_ORIENTATIONS
+ RotationFileReader_close( &headRotReader );
+ RotationFileReader_close( &externalOrientationFileReader );
+ RotationFileReader_close( &refRotReader );
+#else
HeadRotationFileReader_close( &headRotReader );
HeadRotationFileReader_close( &refRotReader );
+#endif
Vector3PairFileReader_close( &referenceVectorReader );
RenderConfigReader_close( &renderConfigReader );
@@ -856,6 +919,10 @@ static bool parseCmdlIVAS_dec(
arg->headrotTrajFileName = NULL;
arg->enableReferenceVectorTracking = false;
arg->referenceVectorTrajFileName = NULL;
+#ifdef EXTERNAL_ORIENTATIONS
+ arg->enableExternalOrientation = false;
+ arg->externalOrientationTrajFileName = NULL;
+#endif
#ifdef SUPPORT_JBM_TRACEFILE
arg->jbmTraceFilename = NULL;
@@ -1166,6 +1233,23 @@ static bool parseCmdlIVAS_dec(
arg->referenceVectorTrajFileName = argv[i];
i++;
}
+#ifdef EXTERNAL_ORIENTATIONS
+ else if ( strcmp( argv_to_upper, "-EXOF" ) == 0 )
+ {
+ arg->enableExternalOrientation = true;
+ i++;
+
+ if ( argc - i <= 4 || argv[i][0] == '-' )
+ {
+ fprintf( stderr, "Error: External orientation file name not specified!\n\n" );
+ usage_dec();
+ return false;
+ }
+
+ arg->externalOrientationTrajFileName = argv[i];
+ i++;
+ }
+#endif
else if ( strcmp( argv_to_upper, "-RENDER_CONFIG" ) == 0 )
{
arg->renderConfigEnabled = true;
@@ -1404,6 +1488,9 @@ static void usage_dec( void )
fprintf( stdout, "-level level : Complexity level, level = (1, 2, 3), will be defined after characterisation. \n" );
fprintf( stdout, " Currently, all values default to level 3 (full functionality).\n" );
#endif
+#ifdef EXTERNAL_ORIENTATIONS
+ fprintf( stdout, "-exof File : External orientation file for external orientation trajectory\n" );
+#endif
#ifdef DEBUG_MODE_INFO
#ifdef DEBUG_MODE_INFO_TWEAK
fprintf( stdout, "-info : specify subfolder name for debug output\n" );
@@ -1591,8 +1678,14 @@ static ivas_error initOnFirstGoodFrame(
static ivas_error decodeG192(
DecArguments arg,
BS_READER_HANDLE hBsReader,
+#ifdef EXTERNAL_ORIENTATIONS
+ RotFileReader *headRotReader,
+ RotFileReader *externalOrientationFileReader,
+ RotFileReader *refRotReader,
+#else
HeadRotFileReader *headRotReader,
HeadRotFileReader *refRotReader,
+#endif
Vector3PairFileReader *referenceVectorReader,
IVAS_DEC_HANDLE hIvasDec,
int16_t *pcmBuf )
@@ -1707,7 +1800,12 @@ static ivas_error decodeG192(
IVAS_QUATERNION quaternion;
if ( ( error = HeadRotationFileReading( refRotReader, &quaternion, NULL ) ) != IVAS_ERR_OK )
{
- fprintf( stderr, "\nError %s while reading reference rotation from %s\n", IVAS_DEC_GetErrorMessage( error ), HeadRotationFileReader_getFilePath( refRotReader ) );
+ fprintf( stderr, "\nError %s while reading reference rotation from %s\n", IVAS_DEC_GetErrorMessage( error ),
+#ifdef EXTERNAL_ORIENTATIONS
+ RotationFileReader_getFilePath( refRotReader ) );
+#else
+ HeadRotationFileReader_getFilePath( refRotReader ) );
+#endif
goto cleanup;
}
@@ -1726,7 +1824,12 @@ static ivas_error decodeG192(
{
if ( ( error = HeadRotationFileReading( headRotReader, &Quaternions[i], &Pos[i] ) ) != IVAS_ERR_OK )
{
- fprintf( stderr, "\nError %s while reading head orientation from %s\n", IVAS_DEC_GetErrorMessage( error ), HeadRotationFileReader_getFilePath( headRotReader ) );
+ fprintf( stderr, "\nError %s while reading head orientation from %s\n", IVAS_DEC_GetErrorMessage( error ),
+#ifdef EXTERNAL_ORIENTATIONS
+ RotationFileReader_getFilePath( headRotReader ) );
+#else
+ HeadRotationFileReader_getFilePath( headRotReader ) );
+#endif
goto cleanup;
}
}
@@ -1737,6 +1840,35 @@ static ivas_error decodeG192(
goto cleanup;
}
}
+
+#ifdef EXTERNAL_ORIENTATIONS
+ if ( arg.enableExternalOrientation )
+ {
+ IVAS_QUATERNION Quaternions[IVAS_MAX_PARAM_SPATIAL_SUBFRAMES];
+ int8_t enableHeadRotation[IVAS_MAX_PARAM_SPATIAL_SUBFRAMES];
+ int8_t enableExternalOrientation[IVAS_MAX_PARAM_SPATIAL_SUBFRAMES];
+ int8_t enableRotationInterpolation[IVAS_MAX_PARAM_SPATIAL_SUBFRAMES];
+ int16_t numFramesToTargetOrientation[IVAS_MAX_PARAM_SPATIAL_SUBFRAMES];
+
+ for ( i = 0; i < IVAS_MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
+ {
+
+ if ( ( error = ExternalOrientationFileReading( externalOrientationFileReader, &Quaternions[i], &enableHeadRotation[i], &enableExternalOrientation[i], &enableRotationInterpolation[i], &numFramesToTargetOrientation[i] ) ) != IVAS_ERR_OK )
+ {
+ fprintf( stderr, "\nError %s while reading external orientation from %s\n", IVAS_DEC_GetErrorMessage( error ),
+ RotationFileReader_getFilePath( externalOrientationFileReader ) );
+ goto cleanup;
+ }
+ }
+
+ if ( ( error = IVAS_DEC_FeedExternalOrientationData( hIvasDec, Quaternions, enableHeadRotation, enableExternalOrientation, enableRotationInterpolation, numFramesToTargetOrientation ) ) != IVAS_ERR_OK )
+ {
+ fprintf( stderr, "\nIVAS_DEC_FeedExternalOrientationData failed: %s\n", IVAS_DEC_GetErrorMessage( error ) );
+ goto cleanup;
+ }
+ }
+#endif
+
/* Run decoder for one frame (get rendered output) */
if ( ( error = IVAS_DEC_GetSamples( hIvasDec, pcmBuf, &nOutSamples ) ) != IVAS_ERR_OK )
{
@@ -2469,8 +2601,14 @@ cleanup:
static ivas_error decodeVariableSpeed(
DecArguments arg,
BS_READER_HANDLE hBsReader,
+#ifdef EXTERNAL_ORIENTATIONS
+ RotFileReader *headRotReader,
+ RotFileReader *externalOrientationFileReader,
+ RotFileReader *refRotReader,
+#else
HeadRotFileReader *headRotReader,
HeadRotFileReader *refRotReader,
+#endif
Vector3PairFileReader *referenceVectorReader,
IVAS_DEC_HANDLE hIvasDec )
@@ -2574,7 +2712,12 @@ static ivas_error decodeVariableSpeed(
IVAS_QUATERNION quaternion;
if ( ( error = HeadRotationFileReading( refRotReader, &quaternion, NULL ) ) != IVAS_ERR_OK )
{
- fprintf( stderr, "\nError %s while reading reference rotation from %s\n", IVAS_DEC_GetErrorMessage( error ), HeadRotationFileReader_getFilePath( refRotReader ) );
+ fprintf( stderr, "\nError %s while reading reference rotation from %s\n", IVAS_DEC_GetErrorMessage( error ),
+#ifdef EXTERNAL_ORIENTATIONS
+ RotationFileReader_getFilePath( refRotReader ) );
+#else
+ HeadRotationFileReader_getFilePath( refRotReader ) );
+#endif
goto cleanup;
}
@@ -2594,7 +2737,12 @@ static ivas_error decodeVariableSpeed(
{
if ( ( error = HeadRotationFileReading( headRotReader, &Quaternions[i], &Pos[i] ) ) != IVAS_ERR_OK )
{
- fprintf( stderr, "\nError %s while reading head orientation from %s\n", IVAS_DEC_GetErrorMessage( error ), HeadRotationFileReader_getFilePath( headRotReader ) );
+ fprintf( stderr, "\nError %s while reading head orientation from %s\n", IVAS_DEC_GetErrorMessage( error ),
+#ifdef EXTERNAL_ORIENTATIONS
+ RotationFileReader_getFilePath( headRotReader ) );
+#else
+ HeadRotationFileReader_getFilePath( headRotReader ) );
+#endif
goto cleanup;
}
}
@@ -2606,6 +2754,34 @@ static ivas_error decodeVariableSpeed(
}
}
+#ifdef EXTERNAL_ORIENTATIONS
+ if ( arg.enableExternalOrientation )
+ {
+ IVAS_QUATERNION Quaternions[IVAS_MAX_PARAM_SPATIAL_SUBFRAMES];
+ int8_t enableHeadRotation[IVAS_MAX_PARAM_SPATIAL_SUBFRAMES];
+ int8_t enableExternalOrientation[IVAS_MAX_PARAM_SPATIAL_SUBFRAMES];
+ int8_t enableRotationInterpolation[IVAS_MAX_PARAM_SPATIAL_SUBFRAMES];
+ int16_t numFramesToTargetOrientation[IVAS_MAX_PARAM_SPATIAL_SUBFRAMES];
+
+ for ( i = 0; i < IVAS_MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
+ {
+
+ if ( ( error = ExternalOrientationFileReading( externalOrientationFileReader, &Quaternions[i], &enableHeadRotation[i], &enableExternalOrientation[i], &enableRotationInterpolation[i], &numFramesToTargetOrientation[i] ) ) != IVAS_ERR_OK )
+ {
+ fprintf( stderr, "\nError %s while reading external orientation from %s\n", IVAS_DEC_GetErrorMessage( error ),
+ RotationFileReader_getFilePath( externalOrientationFileReader ) );
+ goto cleanup;
+ }
+ }
+
+ if ( ( error = IVAS_DEC_FeedExternalOrientationData( hIvasDec, Quaternions, enableHeadRotation, enableExternalOrientation, enableRotationInterpolation, numFramesToTargetOrientation ) ) != IVAS_ERR_OK )
+ {
+ fprintf( stderr, "\nIVAS_DEC_FeedExternalOrientationData failed: %s\n", IVAS_DEC_GetErrorMessage( error ) );
+ goto cleanup;
+ }
+ }
+#endif
+
/* decode and get samples */
do
{
@@ -2827,7 +3003,12 @@ static ivas_error decodeVariableSpeed(
IVAS_QUATERNION quaternion;
if ( ( error = HeadRotationFileReading( refRotReader, &quaternion, NULL ) ) != IVAS_ERR_OK )
{
- fprintf( stderr, "\nError %s while reading reference rotation from %s\n", IVAS_DEC_GetErrorMessage( error ), HeadRotationFileReader_getFilePath( refRotReader ) );
+ fprintf( stderr, "\nError %s while reading reference rotation from %s\n", IVAS_DEC_GetErrorMessage( error ),
+#ifdef EXTERNAL_ORIENTATIONS
+ RotationFileReader_getFilePath( refRotReader ) );
+#else
+ HeadRotationFileReader_getFilePath( refRotReader ) );
+#endif
goto cleanup;
}
@@ -2846,7 +3027,12 @@ static ivas_error decodeVariableSpeed(
{
if ( ( error = HeadRotationFileReading( headRotReader, &Quaternions[i], &Pos[i] ) ) != IVAS_ERR_OK )
{
- fprintf( stderr, "\nError %s while reading head orientation from %s\n", IVAS_DEC_GetErrorMessage( error ), HeadRotationFileReader_getFilePath( headRotReader ) );
+ fprintf( stderr, "\nError %s while reading head orientation from %s\n", IVAS_DEC_GetErrorMessage( error ),
+#ifdef EXTERNAL_ORIENTATIONS
+ RotationFileReader_getFilePath( headRotReader ) );
+#else
+ HeadRotationFileReader_getFilePath( headRotReader ) );
+#endif
goto cleanup;
}
}
@@ -2858,6 +3044,34 @@ static ivas_error decodeVariableSpeed(
}
}
+#ifdef EXTERNAL_ORIENTATIONS
+ if ( arg.enableExternalOrientation )
+ {
+ IVAS_QUATERNION Quaternions[IVAS_MAX_PARAM_SPATIAL_SUBFRAMES];
+ int8_t enableHeadRotation[IVAS_MAX_PARAM_SPATIAL_SUBFRAMES];
+ int8_t enableExternalOrientation[IVAS_MAX_PARAM_SPATIAL_SUBFRAMES];
+ int8_t enableRotationInterpolation[IVAS_MAX_PARAM_SPATIAL_SUBFRAMES];
+ int16_t numFramesToTargetOrientation[IVAS_MAX_PARAM_SPATIAL_SUBFRAMES];
+
+ for ( i = 0; i < IVAS_MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
+ {
+
+ if ( ( error = ExternalOrientationFileReading( externalOrientationFileReader, &Quaternions[i], &enableHeadRotation[i], &enableExternalOrientation[i], &enableRotationInterpolation[i], &numFramesToTargetOrientation[i] ) ) != IVAS_ERR_OK )
+ {
+ fprintf( stderr, "\nError %s while reading external orientation from %s\n", IVAS_DEC_GetErrorMessage( error ),
+ RotationFileReader_getFilePath( externalOrientationFileReader ) );
+ goto cleanup;
+ }
+ }
+
+ if ( ( error = IVAS_DEC_FeedExternalOrientationData( hIvasDec, Quaternions, enableHeadRotation, enableExternalOrientation, enableRotationInterpolation, numFramesToTargetOrientation ) ) != IVAS_ERR_OK )
+ {
+ fprintf( stderr, "\nIVAS_DEC_FeedExternalOrientationData failed: %s\n", IVAS_DEC_GetErrorMessage( error ) );
+ goto cleanup;
+ }
+ }
+#endif
+
/* decode and get samples */
if ( ( error = IVAS_DEC_VoIP_Flush( hIvasDec, nOutSamples, pcmBuf, &nSamplesAvailableNext, &nSamplesFlushed ) ) != IVAS_ERR_OK )
{
diff --git a/apps/renderer.c b/apps/renderer.c
index d285499e224742a0eb0f18376c648493af7860d4..7bee92331fab3321ff1a15ecff32ea6248297a23 100644
--- a/apps/renderer.c
+++ b/apps/renderer.c
@@ -41,7 +41,11 @@
#include "audio_file_writer.h"
#include "cmdl_tools.h"
#include "cmdln_parser.h"
+#ifdef EXTERNAL_ORIENTATIONS
+#include "rotation_file_reader.h"
+#else
#include "head_rotation_file_reader.h"
+#endif
#include "vector3_pair_file_reader.h"
#include "hrtf_file_reader.h"
#include "ism_file_reader.h"
@@ -142,6 +146,9 @@ typedef struct
char headRotationFilePath[RENDERER_MAX_CLI_ARG_LENGTH];
char referenceVectorFilePath[RENDERER_MAX_CLI_ARG_LENGTH];
char referenceRotationFilePath[RENDERER_MAX_CLI_ARG_LENGTH];
+#ifdef EXTERNAL_ORIENTATIONS
+ char externalOrientationFilePath[RENDERER_MAX_CLI_ARG_LENGTH];
+#endif
char customHrtfFilePath[RENDERER_MAX_CLI_ARG_LENGTH];
char renderConfigFilePath[RENDERER_MAX_CLI_ARG_LENGTH];
int8_t orientation_tracking;
@@ -180,6 +187,9 @@ typedef enum
CmdLnOptionId_listFormats,
CmdLnOptionId_inputGain,
CmdLnOptionId_referenceVectorFile,
+#ifdef EXTERNAL_ORIENTATIONS
+ CmdLnOptionId_exteriorOrientationFile,
+#endif
} CmdLnOptionId;
static const CmdLnParser_Option cliOptions[] = {
@@ -299,6 +309,14 @@ static const CmdLnParser_Option cliOptions[] = {
.matchShort = "rvf",
.description = "Reference vector trajectory file for simulation of head tracking (only for BINAURAL and BINAURAL_ROOM outputs)",
},
+#ifdef EXTERNAL_ORIENTATIONS
+ {
+ .id = CmdLnOptionId_exteriorOrientationFile,
+ .match = "exterior_orientation_file",
+ .matchShort = "exof",
+ .description = "External orientation trajectory file for simulation of external orientations",
+ },
+#endif
};
@@ -537,9 +555,15 @@ int main(
char **argv )
{
IVAS_REND_HANDLE hIvasRend;
+#ifdef EXTERNAL_ORIENTATIONS
+ RotFileReader *headRotReader = NULL;
+ RotFileReader *externalOrientationFileReader = NULL;
+ RotFileReader *referenceRotReader = NULL;
+#else
HeadRotFileReader *headRotReader = NULL;
- Vector3PairFileReader *referenceVectorReader = NULL;
HeadRotFileReader *referenceRotReader = NULL;
+#endif
+ Vector3PairFileReader *referenceVectorReader = NULL;
hrtfFileReader *hrtfFileReader = NULL;
IsmPositionProvider *positionProvider;
#ifdef FIX_296_CFG_LFE_SCENE_DESC
@@ -609,10 +633,17 @@ int main(
convert_backslash( args.referenceVectorFilePath );
convert_backslash( args.referenceRotationFilePath );
convert_backslash( args.inLfePanningMatrixFile );
+#ifdef EXTERNAL_ORIENTATIONS
+ convert_backslash( args.externalOrientationFilePath );
+#endif
if ( !isEmptyString( args.headRotationFilePath ) )
{
+#ifdef EXTERNAL_ORIENTATIONS
+ if ( RotationFileReader_open( args.headRotationFilePath, &headRotReader ) != IVAS_ERR_OK )
+#else
if ( HeadRotationFileReader_open( args.headRotationFilePath, &headRotReader ) != IVAS_ERR_OK )
+#endif
{
fprintf( stderr, "Error opening file: %s\n", args.headRotationFilePath );
exit( -1 );
@@ -621,7 +652,11 @@ int main(
if ( !isEmptyString( args.referenceRotationFilePath ) )
{
+#ifdef EXTERNAL_ORIENTATIONS
+ if ( RotationFileReader_open( args.referenceRotationFilePath, &referenceRotReader ) != IVAS_ERR_OK )
+#else
if ( HeadRotationFileReader_open( args.referenceRotationFilePath, &referenceRotReader ) != IVAS_ERR_OK )
+#endif
{
fprintf( stderr, "Error opening file: %s\n", args.referenceRotationFilePath );
exit( -1 );
@@ -636,6 +671,17 @@ int main(
}
}
+#ifdef EXTERNAL_ORIENTATIONS
+ if ( !isEmptyString( args.externalOrientationFilePath ) )
+ {
+ if ( RotationFileReader_open( args.externalOrientationFilePath, &externalOrientationFileReader ) != IVAS_ERR_OK )
+ {
+ fprintf( stderr, "Error opening file: %s\n", args.externalOrientationFilePath );
+ exit( -1 );
+ }
+ }
+#endif
+
if ( !isEmptyString( args.customHrtfFilePath ) )
{
if ( hrtfFileReader_open( args.customHrtfFilePath, &hrtfFileReader ) != IVAS_ERR_OK )
@@ -1066,6 +1112,41 @@ int main(
}
}
+#ifdef EXTERNAL_ORIENTATIONS
+ /* Read from external orientation file if specified */
+ if ( externalOrientationFileReader != NULL )
+ {
+ IVAS_QUATERNION quatBuffer[RENDERER_HEAD_POSITIONS_PER_FRAME];
+ int8_t enableHeadRotation[RENDERER_HEAD_POSITIONS_PER_FRAME];
+ int8_t enableExternalOrientation[RENDERER_HEAD_POSITIONS_PER_FRAME];
+ int8_t enableRotationInterpolation[IVAS_MAX_PARAM_SPATIAL_SUBFRAMES];
+ int16_t numFramesToTargetOrientation[IVAS_MAX_PARAM_SPATIAL_SUBFRAMES];
+
+ for ( i = 0; i < RENDERER_HEAD_POSITIONS_PER_FRAME; i++ )
+ {
+ if ( ( error = ExternalOrientationFileReading( externalOrientationFileReader, &quatBuffer[i], &enableHeadRotation[i], &enableExternalOrientation[i], &enableRotationInterpolation[i], &numFramesToTargetOrientation[i] ) ) != IVAS_ERR_OK )
+ {
+ fprintf( stderr, "Error in External Orientation File Reading: %s\n", ivas_error_to_string( error ) );
+ exit( -1 );
+ }
+ }
+
+ if ( ( error = IVAS_REND_SetExternalOrientation( hIvasRend, quatBuffer, enableHeadRotation, enableExternalOrientation, enableRotationInterpolation, numFramesToTargetOrientation ) ) != IVAS_ERR_OK )
+ {
+ fprintf( stderr, "Error setting External Orientation: %s\n", ivas_error_to_string( error ) );
+ exit( -1 );
+ }
+ }
+
+ /* Combine external orientations and head rotation */
+
+ if ( ( error = IVAS_REND_CombineHeadAndExternalOrientation( hIvasRend ) ) != IVAS_ERR_OK )
+ {
+ fprintf( stderr, "Error combining external and head orientations: %s\n", ivas_error_to_string( error ) );
+ exit( -1 );
+ }
+#endif
+
for ( i = 0; i < args.inConfig.numMultiChannelBuses; ++i )
{
if ( ( error = IVAS_REND_GetInputNumChannels( hIvasRend, mcIds[i], &numChannels ) ) != IVAS_ERR_OK )
@@ -1244,9 +1325,15 @@ int main(
#endif
AudioFileReader_close( &audioReader );
AudioFileWriter_close( &audioWriter );
+#ifdef EXTERNAL_ORIENTATIONS
+ RotationFileReader_close( &headRotReader );
+ RotationFileReader_close( &externalOrientationFileReader );
+ RotationFileReader_close( &referenceRotReader );
+#else
HeadRotationFileReader_close( &headRotReader );
- Vector3PairFileReader_close( &referenceVectorReader );
HeadRotationFileReader_close( &referenceRotReader );
+#endif
+ Vector3PairFileReader_close( &referenceVectorReader );
hrtfFileReader_close( &hrtfFileReader );
IVAS_REND_Close( &hIvasRend );
IsmPositionProvider_close( positionProvider );
@@ -1712,6 +1799,9 @@ static CmdlnArgs defaultArgs(
clearString( args.referenceRotationFilePath );
clearString( args.customHrtfFilePath );
clearString( args.renderConfigFilePath );
+#ifdef EXTERNAL_ORIENTATIONS
+ clearString( args.externalOrientationFilePath );
+#endif
args.orientation_tracking = HEAD_ORIENT_TRK_NONE;
args.nonDiegeticPan = 0;
@@ -1802,6 +1892,12 @@ static void parseOption(
assert( numOptionValues == 1 );
strncpy( args->referenceRotationFilePath, optionValues[0], RENDERER_MAX_CLI_ARG_LENGTH - 1 );
break;
+#ifdef EXTERNAL_ORIENTATIONS
+ case CmdLnOptionId_exteriorOrientationFile:
+ assert( numOptionValues == 1 );
+ strncpy( args->externalOrientationFilePath, optionValues[0], RENDERER_MAX_CLI_ARG_LENGTH - 1 );
+ break;
+#endif
case CmdLnOptionId_customHrtfFile:
assert( numOptionValues == 1 );
strncpy( args->customHrtfFilePath, optionValues[0], RENDERER_MAX_CLI_ARG_LENGTH - 1 );
diff --git a/lib_com/ivas_error.h b/lib_com/ivas_error.h
index 0fae8ff215c57979cdd682cf5600f1d1f62260fa..eb71119d9e213ba56eed93eba2fc94b7b79d7490 100644
--- a/lib_com/ivas_error.h
+++ b/lib_com/ivas_error.h
@@ -75,6 +75,9 @@ typedef enum
IVAS_ERR_WRONG_MODE,
IVAS_ERR_INVALID_OUTPUT_FORMAT,
IVAS_ERR_HEAD_ROTATION_NOT_SUPPORTED,
+#ifdef EXTERNAL_ORIENTATIONS
+ IVAS_ERR_EXT_ORIENTATION_NOT_SUPPORTED,
+#endif
IVAS_ERR_INVALID_HRTF,
IVAS_ERR_INVALID_INPUT_FORMAT,
IVAS_ERR_INVALID_INDEX, /* ToDo: should be merged with IVAS_ERR_INDEX_OUT_OF_BOUNDS */
@@ -232,6 +235,10 @@ static inline const char *ivas_error_to_string( ivas_error error_code )
return "Wrong mode";
case IVAS_ERR_HEAD_ROTATION_NOT_SUPPORTED:
return "Head rotation not supported";
+#ifdef EXTERNAL_ORIENTATIONS
+ case IVAS_ERR_EXT_ORIENTATION_NOT_SUPPORTED:
+ return "External orientation not supported";
+#endif
case IVAS_ERR_INVALID_HRTF:
return "Unsupported HRTF filter set";
case IVAS_ERR_INVALID_INPUT_FORMAT:
diff --git a/lib_com/ivas_prot.h b/lib_com/ivas_prot.h
index 2ad9dc88054636fee8eb4e3150691be45a048854..b4759ee7208a8323918efd36d697c50d8db25f5d 100644
--- a/lib_com/ivas_prot.h
+++ b/lib_com/ivas_prot.h
@@ -118,7 +118,7 @@ ivas_error ivas_spar_md_enc_init
const int16_t sba_order /* i : Ambisonic (SBA) order */
);
-ivas_error ivas_sba_enc_reconfigure(
+ivas_error ivas_sba_enc_reconfigure(
Encoder_Struct *st_ivas /* i/o: IVAS encoder structure */
);
/*! r: maximum SBA metadata bit-budget */
@@ -822,11 +822,11 @@ void ivas_jbm_dec_get_md_map(
int16_t *map /* o : metadata index map */
);
-int16_t ivas_jbm_dec_get_num_tc_channels(
+int16_t ivas_jbm_dec_get_num_tc_channels(
Decoder_Struct *st_ivas /* i : IVAS decoder handle */
);
-TC_BUFFER_MODE ivas_jbm_dec_get_tc_buffer_mode(
+TC_BUFFER_MODE ivas_jbm_dec_get_tc_buffer_mode(
Decoder_Struct *st_ivas /* i : IVAS decoder handle */
);
@@ -3181,7 +3181,7 @@ void restore_metadata_buffer(
#ifndef IND_LIST_DYN
const int16_t last_ind_start,
#endif
- const int16_t bit_pos_start
+ const int16_t bit_pos_start
);
/*! r: codeword index */
@@ -3526,7 +3526,7 @@ void ivas_dirac_enc(
const int16_t dtx_vad, /* i : DTX vad flag */
const IVAS_FORMAT ivas_format, /* i : ivas format */
int16_t hodirac_flag /* i : hodirac flag */
-);
+);
ivas_error ivas_dirac_config(
void *st_ivas, /* i/o: IVAS encoder/decoder state structure */
const int16_t enc_dec /* i : encoder or decoder flag */
@@ -3547,7 +3547,7 @@ void ivas_get_dirac_sba_max_md_bits(
int16_t *bits_frame_nominal,
int16_t *metadata_max_bits,
int16_t *qmetadata_max_bit_req,
- const int16_t nbands
+ const int16_t nbands
);
ivas_error ivas_dirac_sba_config(
@@ -4831,25 +4831,25 @@ int16_t ivas_get_bits_to_encode(
int32_t val
);
-void ivas_huffman_encode(
- ivas_huffman_cfg_t *huff_cfg,
- int16_t in,
- int16_t *hcode,
- int16_t *hlen
+void ivas_huffman_encode(
+ ivas_huffman_cfg_t *huff_cfg,
+ int16_t in,
+ int16_t *hcode,
+ int16_t *hlen
);
-void ivas_spar_huff_coeffs_com_init(
- ivas_huff_coeffs_t *pHuff_coeffs,
- ivas_spar_md_com_cfg *pSpar_cfg,
- const int16_t table_idx,
- const int16_t enc_dec
+void ivas_spar_huff_coeffs_com_init(
+ ivas_huff_coeffs_t *pHuff_coeffs,
+ ivas_spar_md_com_cfg *pSpar_cfg,
+ const int16_t table_idx,
+ const int16_t enc_dec
);
-void ivas_spar_arith_coeffs_com_init(
+void ivas_spar_arith_coeffs_com_init(
ivas_arith_coeffs_t *pArith_coeffs,
ivas_spar_md_com_cfg *pSpar_cfg,
- const int16_t table_idx,
- const int16_t enc_dec
+ const int16_t table_idx,
+ const int16_t enc_dec
);
int16_t ivas_arith_encode_cmplx_cell_array(
@@ -4866,74 +4866,74 @@ int16_t ivas_arith_encode_cmplx_cell_array(
const int16_t wc_strat_arith
);
-ivas_error ivas_huffman_decode(
- ivas_huffman_cfg_t *huff_cfg,
- Decoder_State *st0,
- int16_t *dec_out
+ivas_error ivas_huffman_decode(
+ ivas_huffman_cfg_t *huff_cfg,
+ Decoder_State *st0,
+ int16_t *dec_out
);
-void ivas_arith_decode_cmplx_cell_array(
- ivas_arith_t *pArith_re,
- ivas_arith_t *pArith_re_diff,
+void ivas_arith_decode_cmplx_cell_array(
+ ivas_arith_t *pArith_re,
+ ivas_arith_t *pArith_re_diff,
Decoder_State *st0,
- ivas_cell_dim_t *pCell_dims,
- int16_t *pDo_diff, const int16_t nB,
+ ivas_cell_dim_t *pCell_dims,
+ int16_t *pDo_diff, const int16_t nB,
int16_t *pSymbol_re,
- int16_t *pSymbol_re_old
+ int16_t *pSymbol_re_old
);
-void ivas_ari_start_decoding_14bits_ext_1_lfe(
+void ivas_ari_start_decoding_14bits_ext_1_lfe(
Decoder_State *st,
- Tastat *s,
- int16_t *extra_bits_read
+ Tastat *s,
+ int16_t *extra_bits_read
);
-uint16_t ivas_ari_decode_14bits_bit_ext_1_lfe(
- Decoder_State *st, Tastat *s,
- const uint16_t *cum_freq,
- int16_t *extra_bits_read
+uint16_t ivas_ari_decode_14bits_bit_ext_1_lfe(
+ Decoder_State *st, Tastat *s,
+ const uint16_t *cum_freq,
+ int16_t *extra_bits_read
);
-void ivas_ari_done_decoding_14bits_ext_1_lfe(
- Decoder_State *st,
- const int16_t extra_bits_read
+void ivas_ari_done_decoding_14bits_ext_1_lfe(
+ Decoder_State *st,
+ const int16_t extra_bits_read
);
-void ivas_ari_done_encoding_14bits(
- BSTR_ENC_HANDLE hBstr, Tastat *s
+void ivas_ari_done_encoding_14bits(
+ BSTR_ENC_HANDLE hBstr, Tastat *s
);
-void ivas_ari_encode_14bits_ext(
- BSTR_ENC_HANDLE hBstr,
- Tastat *s,
- int32_t symbol,
- const uint16_t *cum_freq
+void ivas_ari_encode_14bits_ext(
+ BSTR_ENC_HANDLE hBstr,
+ Tastat *s,
+ int32_t symbol,
+ const uint16_t *cum_freq
);
-void ivas_wrap_arround(
- int16_t *pArr,
+void ivas_wrap_arround(
+ int16_t *pArr,
const int16_t min_val,
- const int16_t max_val,
- const int16_t length
+ const int16_t max_val,
+ const int16_t length
);
-void ivas_get_cum_freq_model(
- const int16_t *pFreq_model,
- const int16_t length,
- int16_t *pCum_freq_model
+void ivas_get_cum_freq_model(
+ const int16_t *pFreq_model,
+ const int16_t length,
+ int16_t *pCum_freq_model
);
-int16_t ivas_map_num_pred_r_to_idx(
- const int16_t num_quant_points_pred_r,
- const int16_t active_w_flag
+int16_t ivas_map_num_pred_r_to_idx(
+ const int16_t num_quant_points_pred_r,
+ const int16_t active_w_flag
);
-int16_t ivas_map_num_drct_r_to_idx(
- const int16_t num_quant_points_drct_r
+int16_t ivas_map_num_drct_r_to_idx(
+ const int16_t num_quant_points_drct_r
);
-int16_t ivas_map_num_decd_r_to_idx(
- const int16_t num_quant_points_decd_r
+int16_t ivas_map_num_decd_r_to_idx(
+ const int16_t num_quant_points_decd_r
);
/* Quantization utilities */
@@ -5160,6 +5160,10 @@ void ivas_binaural_cldfb_sf(
void ivas_binRenderer(
BINAURAL_RENDERER_HANDLE hBinRenderer, /* i/o: fastconv binaural renderer handle */
HEAD_TRACK_DATA_HANDLE hHeadTrackData, /* i/o: head track handle */
+#ifdef EXTERNAL_ORIENTATIONS
+ COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, /* i : combined head and external orientation handle */
+ int16_t subframe_idx, /* i : subframe index */
+#endif
const int16_t numTimeSlots, /* i: : number of time slots to process */
float Cldfb_RealBuffer_Binaural[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* o : Binaural signals */
float Cldfb_ImagBuffer_Binaural[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* o : Binaural signals */
diff --git a/lib_com/options.h b/lib_com/options.h
index 555c98b76064c134cd7e1e9d8f2802275cf6ca49..5e87b2e031e6ca889d6e8901a8724b02c469b27c 100755
--- a/lib_com/options.h
+++ b/lib_com/options.h
@@ -168,6 +168,7 @@
#define FIX_511_OPTIMIZE_PARAMBIN_GAIN_FETCH /* Nokia: Issue 511, significant optimization of parametric binauralizer gain fetching. */
#define FIX_531_BWS_ISM_BFI /* VA: issue 531: fix MemorySanitizer: use-of-uninitialized-value in ISM2 rate switching with frame errors */
+#define EXTERNAL_ORIENTATIONS /* Nokia: Contribution 41: (external) orientation information handling */
/* ################## End DEVELOPMENT switches ######################### */
/* clang-format on */
diff --git a/lib_dec/ivas_binRenderer_internal.c b/lib_dec/ivas_binRenderer_internal.c
index 2e0c4f782925cee27c75aebefb444e789066c918..074a7c3cdbfc9fcd868ce7ea9292c244f17d9d01 100644
--- a/lib_dec/ivas_binRenderer_internal.c
+++ b/lib_dec/ivas_binRenderer_internal.c
@@ -805,7 +805,11 @@ ivas_error ivas_binRenderer_open(
ivas_dirac_dec_get_response( (int16_t) ls_azimuth_CICP19[k], (int16_t) ls_elevation_CICP19[k], hBinRenderer->hReverb->foa_enc[k], 1 );
}
}
+#ifdef EXTERNAL_ORIENTATIONS
+ else if ( st_ivas->ivas_format == MC_FORMAT && ( st_ivas->hDecoderConfig->Opt_Headrotation || st_ivas->hDecoderConfig->Opt_ExternalOrientation ) )
+#else
else if ( st_ivas->ivas_format == MC_FORMAT && st_ivas->hDecoderConfig->Opt_Headrotation )
+#endif
{
if ( ( error = efap_init_data( &( st_ivas->hEFAPdata ), st_ivas->hIntSetup.ls_azimuth, st_ivas->hIntSetup.ls_elevation, st_ivas->hIntSetup.nchan_out_woLFE, EFAP_MODE_EFAP ) ) != IVAS_ERR_OK )
{
@@ -1036,7 +1040,12 @@ void ivas_binaural_cldfb(
}
/* Implement binaural rendering */
+#ifdef EXTERNAL_ORIENTATIONS
+ ivas_binRenderer( st_ivas->hBinRenderer, st_ivas->hHeadTrackData, st_ivas->hCombinedOrientationData, subframeIdx, JBM_CLDFB_SLOTS_IN_SUBFRAME, Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, Cldfb_RealBuffer, Cldfb_ImagBuffer );
+#else
ivas_binRenderer( st_ivas->hBinRenderer, st_ivas->hHeadTrackData, JBM_CLDFB_SLOTS_IN_SUBFRAME, Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, Cldfb_RealBuffer, Cldfb_ImagBuffer );
+#endif
+
/* Implement CLDFB synthesis */
for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
{
@@ -1127,7 +1136,11 @@ void ivas_binaural_cldfb_sf(
}
/* Implement binaural rendering */
+#ifdef EXTERNAL_ORIENTATIONS
+ ivas_binRenderer( st_ivas->hBinRenderer, st_ivas->hHeadTrackData, st_ivas->hCombinedOrientationData, subframeIdx, st_ivas->hTcBuffer->subframe_nbslots[subframeIdx], Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, Cldfb_RealBuffer, Cldfb_ImagBuffer );
+#else
ivas_binRenderer( st_ivas->hBinRenderer, st_ivas->hHeadTrackData, st_ivas->hTcBuffer->subframe_nbslots[subframeIdx], Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, Cldfb_RealBuffer, Cldfb_ImagBuffer );
+#endif
/* Implement CLDFB synthesis */
for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
@@ -1161,8 +1174,12 @@ void ivas_binaural_cldfb_sf(
*-------------------------------------------------------------------------*/
void ivas_binRenderer(
- BINAURAL_RENDERER_HANDLE hBinRenderer, /* i/o: binaural renderer handle */
- HEAD_TRACK_DATA_HANDLE hHeadTrackData, /* i/o: head track handle */
+ BINAURAL_RENDERER_HANDLE hBinRenderer, /* i/o: binaural renderer handle */
+ HEAD_TRACK_DATA_HANDLE hHeadTrackData, /* i/o: head track handle */
+#ifdef EXTERNAL_ORIENTATIONS
+ COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, /* i : combined head and external orientation handle */
+ int16_t subframe_idx, /* i : subframe index */
+#endif
const int16_t numTimeSlots, /* i : number of time slots to render*/
float Cldfb_RealBuffer_Binaural[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* o : Binaural signals */
float Cldfb_ImagBuffer_Binaural[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* o : Binaural signals */
@@ -1186,25 +1203,43 @@ void ivas_binRenderer(
}
/* Head rotation in HOA3 or CICPx */
- if ( hHeadTrackData && hHeadTrackData->num_quaternions >= 0 && hBinRenderer->rotInCldfb )
+ if ( hHeadTrackData
+#ifdef EXTERNAL_ORIENTATIONS
+ && hCombinedOrientationData != NULL && hCombinedOrientationData->enableCombinedOrientation[subframe_idx]
+#else
+ && hHeadTrackData->num_quaternions >= 0
+#endif
+ && hBinRenderer->rotInCldfb )
{
if ( hBinRenderer->hInputSetup->is_loudspeaker_setup == 0 )
{
/* Rotation in SHD (HOA3) */
if ( hHeadTrackData->shd_rot_max_order == -1 )
{
+#ifdef EXTERNAL_ORIENTATIONS
+ rotateFrame_shd_cldfb( RealBuffer, ImagBuffer, hCombinedOrientationData->Rmat[subframe_idx], hBinRenderer->hInputSetup->nchan_out_woLFE, numTimeSlots, 3 );
+#else
QuatToRotMat( hHeadTrackData->Quaternions[hHeadTrackData->num_quaternions++], hHeadTrackData->Rmat );
rotateFrame_shd_cldfb( RealBuffer, ImagBuffer, hHeadTrackData->Rmat, hBinRenderer->hInputSetup->nchan_out_woLFE, numTimeSlots, 3 );
+#endif
}
else if ( hHeadTrackData->shd_rot_max_order > 0 )
{
+#ifdef EXTERNAL_ORIENTATIONS
+ rotateFrame_shd_cldfb( RealBuffer, ImagBuffer, hCombinedOrientationData->Rmat[subframe_idx], hBinRenderer->hInputSetup->nchan_out_woLFE, numTimeSlots, hHeadTrackData->shd_rot_max_order );
+#else
rotateFrame_shd_cldfb( RealBuffer, ImagBuffer, hHeadTrackData->Rmat, hBinRenderer->hInputSetup->nchan_out_woLFE, numTimeSlots, hHeadTrackData->shd_rot_max_order );
+#endif
}
}
else
{
/* Rotation in SD (CICPx) */
+#ifdef EXTERNAL_ORIENTATIONS
+ rotateFrame_sd_cldfb( hCombinedOrientationData->Rmat[subframe_idx], RealBuffer, ImagBuffer, hBinRenderer->hInputSetup, hBinRenderer->hEFAPdata, numTimeSlots, hBinRenderer->conv_band );
+#else
rotateFrame_sd_cldfb( hHeadTrackData, RealBuffer, ImagBuffer, hBinRenderer->hInputSetup, hBinRenderer->hEFAPdata, numTimeSlots, hBinRenderer->conv_band );
+#endif
}
}
diff --git a/lib_dec/ivas_dec.c b/lib_dec/ivas_dec.c
index fb1b367767832901b890a4eba39116f58a86f1f8..aef3d177f9782210f47075c989f1e610a472f409 100644
--- a/lib_dec/ivas_dec.c
+++ b/lib_dec/ivas_dec.c
@@ -104,6 +104,18 @@ ivas_error ivas_dec(
p_output[n] = &output[n][0];
}
+#ifdef EXTERNAL_ORIENTATIONS
+ /*----------------------------------------------------------------*
+ * Combine orientations
+ *----------------------------------------------------------------*/
+
+ if ( ( error = combine_external_and_head_orientations_dec( st_ivas->hHeadTrackData, st_ivas->hExtOrientationData,
+ st_ivas->hCombinedOrientationData ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+#endif
+
/*----------------------------------------------------------------*
* Decoding + Rendering
*----------------------------------------------------------------*/
@@ -187,7 +199,11 @@ ivas_error ivas_dec(
{
ivas_param_ism_params_to_masa_param_mapping( st_ivas );
+#ifdef EXTERNAL_ORIENTATIONS
+ ivas_dirac_dec_binaural( st_ivas, st_ivas->hCombinedOrientationData, output, st_ivas->nchan_transport );
+#else
ivas_dirac_dec_binaural( st_ivas, output, st_ivas->nchan_transport );
+#endif
}
else if ( st_ivas->renderer_type == RENDERER_MONO_DOWNMIX )
{
@@ -407,7 +423,11 @@ ivas_error ivas_dec(
/* Loudspeakers, Ambisonics or Binaural rendering */
if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC )
{
+#ifdef EXTERNAL_ORIENTATIONS
+ ivas_dirac_dec_binaural( st_ivas, st_ivas->hCombinedOrientationData, output, nchan_remapped );
+#else
ivas_dirac_dec_binaural( st_ivas, output, nchan_remapped );
+#endif
}
else if ( st_ivas->ivas_format == MASA_FORMAT )
{
@@ -465,9 +485,12 @@ ivas_error ivas_dec(
if ( st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV || st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV_ROOM )
{
if ( ( error = ivas_rend_crendProcess( st_ivas->hCrendWrapper, st_ivas->intern_config, st_ivas->hOutSetup.output_config, st_ivas->hDecoderConfig,
- st_ivas->hHeadTrackData, &st_ivas->hIntSetup, st_ivas->hEFAPdata,
- p_output,
- output_Fs ) ) != IVAS_ERR_OK )
+#ifdef EXTERNAL_ORIENTATIONS
+ st_ivas->hCombinedOrientationData,
+#else
+ st_ivas->hHeadTrackData,
+#endif
+ &st_ivas->hIntSetup, st_ivas->hEFAPdata, p_output, output_Fs ) ) != IVAS_ERR_OK )
{
return error;
}
@@ -524,7 +547,13 @@ ivas_error ivas_dec(
/* Rendering */
if ( st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV || st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV_ROOM )
{
- if ( ( error = ivas_rend_crendProcess( st_ivas->hCrendWrapper, st_ivas->intern_config, st_ivas->hOutSetup.output_config, st_ivas->hDecoderConfig, st_ivas->hHeadTrackData, &st_ivas->hIntSetup, st_ivas->hEFAPdata, p_output, output_Fs ) ) != IVAS_ERR_OK )
+ if ( ( error = ivas_rend_crendProcess( st_ivas->hCrendWrapper, st_ivas->intern_config, st_ivas->hOutSetup.output_config, st_ivas->hDecoderConfig,
+#ifdef EXTERNAL_ORIENTATIONS
+ st_ivas->hCombinedOrientationData,
+#else
+ st_ivas->hHeadTrackData,
+#endif
+ &st_ivas->hIntSetup, st_ivas->hEFAPdata, p_output, output_Fs ) ) != IVAS_ERR_OK )
{
return error;
}
@@ -667,7 +696,11 @@ ivas_error ivas_dec(
/* Rendering */
if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC )
{
+#ifdef EXTERNAL_ORIENTATIONS
+ ivas_dirac_dec_binaural( st_ivas, st_ivas->hCombinedOrientationData, output, st_ivas->nchan_transport );
+#else
ivas_dirac_dec_binaural( st_ivas, output, st_ivas->nchan_transport );
+#endif
}
else if ( st_ivas->renderer_type == RENDERER_DIRAC || st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) /* rendering to CICPxx and Ambisonics */
{
diff --git a/lib_dec/ivas_dirac_dec.c b/lib_dec/ivas_dirac_dec.c
index feb61ab063dfb9ab27918340a0282a76c68b6a23..5877dc4738b0eaf5b30eca684f4494924b698334 100644
--- a/lib_dec/ivas_dirac_dec.c
+++ b/lib_dec/ivas_dirac_dec.c
@@ -2626,11 +2626,19 @@ void ivas_dirac_dec_render_sf(
set_zero( onset_filter_subframe, hDirAC->num_freq_bands );
}
+#ifdef EXTERNAL_ORIENTATIONS
+ if ( st_ivas->hHeadTrackData && st_ivas->hCombinedOrientationData && st_ivas->hCombinedOrientationData->enableCombinedOrientation[subframe_idx] )
+#else
if ( st_ivas->hHeadTrackData )
+#endif
{
+#ifdef EXTERNAL_ORIENTATIONS
+ p_Rmat = &st_ivas->hCombinedOrientationData->Rmat[subframe_idx][0][0];
+#else
QuatToRotMat( st_ivas->hHeadTrackData->Quaternions[st_ivas->hHeadTrackData->num_quaternions++], st_ivas->hHeadTrackData->Rmat );
p_Rmat = &st_ivas->hHeadTrackData->Rmat[0][0];
+#endif
if ( st_ivas->hHeadTrackData->shd_rot_max_order == 0 )
{
@@ -2705,8 +2713,11 @@ void ivas_dirac_dec_render_sf(
set_zero( surCohRatio, hDirAC->num_freq_bands );
}
}
-
+#ifdef EXTERNAL_ORIENTATIONS
+ if ( st_ivas->hCombinedOrientationData && st_ivas->hCombinedOrientationData->enableCombinedOrientation[subframe_idx] && st_ivas->hHeadTrackData->shd_rot_max_order == 1 )
+#else
if ( st_ivas->hDecoderConfig->Opt_Headrotation && st_ivas->hHeadTrackData->shd_rot_max_order == 1 )
+#endif
{
ivas_dirac_dec_compute_directional_responses( hDirAC,
st_ivas->hVBAPdata,
@@ -2809,7 +2820,11 @@ void ivas_dirac_dec_render_sf(
if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD )
{
+#ifdef EXTERNAL_ORIENTATIONS
+ if ( st_ivas->hCombinedOrientationData && st_ivas->hCombinedOrientationData->enableCombinedOrientation[subframe_idx] && st_ivas->hHeadTrackData->shd_rot_max_order == 0 )
+#else
if ( st_ivas->hDecoderConfig->Opt_Headrotation && st_ivas->hHeadTrackData->shd_rot_max_order == 0 )
+#endif
{
protoSignalComputation_shd( Cldfb_RealBuffer, Cldfb_ImagBuffer,
hDirAC->h_output_synthesis_psd_state.proto_direct_buffer_f,
@@ -3056,7 +3071,11 @@ void ivas_dirac_dec_render_sf(
}
/*Compute PSDs*/
+#ifdef EXTERNAL_ORIENTATIONS
+ if ( st_ivas->hCombinedOrientationData && st_ivas->hCombinedOrientationData->enableCombinedOrientation[subframe_idx] && st_ivas->hHeadTrackData->shd_rot_max_order > 0 )
+#else
if ( st_ivas->hDecoderConfig->Opt_Headrotation && st_ivas->hHeadTrackData->shd_rot_max_order > 0 )
+#endif
{
ivas_dirac_dec_output_synthesis_process_slot( reference_power,
p_onset_filter,
@@ -3223,6 +3242,10 @@ void ivas_dirac_dec_render_sf(
/* Perform binaural rendering */
ivas_binRenderer( st_ivas->hBinRenderer,
st_ivas->hHeadTrackData,
+#ifdef EXTERNAL_ORIENTATIONS
+ st_ivas->hCombinedOrientationData,
+ subframe_idx,
+#endif
hDirAC->subframe_nbslots[subframe_idx],
Cldfb_RealBuffer_Binaural,
Cldfb_ImagBuffer_Binaural,
diff --git a/lib_dec/ivas_init_dec.c b/lib_dec/ivas_init_dec.c
index 4bb061b572c63b0ad6daa655e65276e35202466d..9d5ad35d5195dd8c905183aded389c71b9b03625 100644
--- a/lib_dec/ivas_init_dec.c
+++ b/lib_dec/ivas_init_dec.c
@@ -589,6 +589,32 @@ ivas_error ivas_init_decoder_front(
}
}
+#ifdef EXTERNAL_ORIENTATIONS
+ /*-------------------------------------------------------------------*
+ * Allocate and initialize external orientation handle
+ *--------------------------------------------------------------------*/
+
+ if ( st_ivas->hDecoderConfig->Opt_ExternalOrientation )
+ {
+ if ( ( error = ivas_external_orientation_open( &( st_ivas->hExtOrientationData ) ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+ }
+
+ /*-------------------------------------------------------------------*
+ * Allocate and initialize combined orientation handle
+ *--------------------------------------------------------------------*/
+
+ if ( st_ivas->hDecoderConfig->Opt_Headrotation || st_ivas->hDecoderConfig->Opt_ExternalOrientation )
+ {
+ if ( ( error = ivas_combined_orientation_open( &( st_ivas->hCombinedOrientationData ) ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+ }
+#endif
+
/*-------------------------------------------------------------------*
* Allocate HRTF binary handle
*--------------------------------------------------------------------*/
@@ -1266,7 +1292,11 @@ ivas_error ivas_init_decoder(
}
else if ( st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV || st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV_ROOM )
{
+#ifdef EXTERNAL_ORIENTATIONS
+ if ( st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV_ROOM && st_ivas->ivas_format == MC_FORMAT && ( st_ivas->hDecoderConfig->Opt_Headrotation || st_ivas->hDecoderConfig->Opt_ExternalOrientation ) )
+#else
if ( st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV_ROOM && st_ivas->ivas_format == MC_FORMAT && st_ivas->hDecoderConfig->Opt_Headrotation )
+#endif
{
if ( ( error = efap_init_data( &( st_ivas->hEFAPdata ), st_ivas->hIntSetup.ls_azimuth, st_ivas->hIntSetup.ls_elevation, st_ivas->hIntSetup.nchan_out_woLFE, EFAP_MODE_EFAP ) ) != IVAS_ERR_OK )
{
@@ -1627,6 +1657,10 @@ void ivas_initialize_handles_dec(
st_ivas->hHrtfTD = NULL;
st_ivas->hLsSetupCustom = NULL;
st_ivas->hRenderConfig = NULL;
+#ifdef EXTERNAL_ORIENTATIONS
+ st_ivas->hExtOrientationData = NULL;
+ st_ivas->hCombinedOrientationData = NULL;
+#endif
st_ivas->hTcBuffer = NULL;
@@ -1788,6 +1822,14 @@ void ivas_destroy_dec(
/* Head track data handle */
ivas_headTrack_close( &st_ivas->hHeadTrackData );
+#ifdef EXTERNAL_ORIENTATIONS
+ /* External orientation data handle */
+ ivas_external_orientation_close( &st_ivas->hExtOrientationData );
+
+ /* Combined orientation data handle */
+ ivas_combined_orientation_close( &st_ivas->hCombinedOrientationData );
+#endif
+
/* Time Domain binaural renderer handle */
if ( st_ivas->hBinRendererTd != NULL )
{
@@ -2087,6 +2129,16 @@ static ivas_error doSanityChecks_IVAS(
}
}
+#ifdef EXTERNAL_ORIENTATIONS
+ if ( st_ivas->hDecoderConfig->Opt_ExternalOrientation )
+ {
+ if ( !( output_config == AUDIO_CONFIG_BINAURAL || output_config == AUDIO_CONFIG_BINAURAL_ROOM ) )
+ {
+ return IVAS_ERROR( IVAS_ERR_EXT_ORIENTATION_NOT_SUPPORTED, "Wrong set-up: External orientation not supported in this configuration" );
+ }
+ }
+#endif
+
#ifdef DEBUGGING
if ( ( st_ivas->hDecoderConfig->force_rend == FORCE_TD_RENDERER ) && ( ( st_ivas->ivas_format != MC_FORMAT && st_ivas->ivas_format != ISM_FORMAT ) || output_config != AUDIO_CONFIG_BINAURAL || ( st_ivas->ivas_format == ISM_FORMAT && st_ivas->ism_mode == ISM_MODE_PARAM ) || ( st_ivas->ivas_format == MC_FORMAT && ( st_ivas->mc_mode != MC_MODE_MCT && st_ivas->mc_mode != MC_MODE_PARAMUPMIX ) ) ) )
{
diff --git a/lib_dec/ivas_ism_renderer.c b/lib_dec/ivas_ism_renderer.c
index c6ca4b3b7bc66f71ea415faadc294c09935a5ba2..2362979ff6c795fdf640e1f638b80351467d12dc 100644
--- a/lib_dec/ivas_ism_renderer.c
+++ b/lib_dec/ivas_ism_renderer.c
@@ -121,7 +121,9 @@ void ivas_ism_render(
float g1, g2;
int16_t nchan_ism, nchan_out_woLFE, lfe_index;
int16_t azimuth, elevation;
+#ifndef EXTERNAL_ORIENTATIONS
float Rmat[3][3];
+#endif
nchan_ism = st_ivas->nchan_ism;
nchan_out_woLFE = st_ivas->hIntSetup.nchan_out_woLFE;
@@ -143,11 +145,13 @@ void ivas_ism_render(
set_f( output_f[i], 0.0f, output_frame );
}
+#ifndef EXTERNAL_ORIENTATIONS
if ( st_ivas->hHeadTrackData != NULL && st_ivas->hHeadTrackData->num_quaternions >= 0 )
{
/* Calculate rotation matrix from the quaternion */
QuatToRotMat( st_ivas->hHeadTrackData->Quaternions[st_ivas->hHeadTrackData->num_quaternions++], Rmat );
}
+#endif
for ( i = 0; i < nchan_ism; i++ )
{
@@ -160,10 +164,17 @@ void ivas_ism_render(
}
else
{
+#ifdef EXTERNAL_ORIENTATIONS
+ /* Combined rotation: rotate the object positions depending the head and external orientations */
+ if ( st_ivas->hCombinedOrientationData != NULL && st_ivas->hCombinedOrientationData->enableCombinedOrientation[0] == 1 )
+ {
+ rotateAziEle( st_ivas->hIsmMetaData[i]->azimuth, st_ivas->hIsmMetaData[i]->elevation, &azimuth, &elevation, st_ivas->hCombinedOrientationData->Rmat[0], st_ivas->hIntSetup.is_planar_setup );
+#else
/* Head rotation: rotate the object positions depending the head's orientation */
if ( st_ivas->hHeadTrackData != NULL && st_ivas->hHeadTrackData->num_quaternions >= 0 && !st_ivas->hIsmMetaData[i]->non_diegetic_flag )
{
rotateAziEle( st_ivas->hIsmMetaData[i]->azimuth, st_ivas->hIsmMetaData[i]->elevation, &azimuth, &elevation, Rmat, st_ivas->hIntSetup.is_planar_setup );
+#endif
}
else
{
diff --git a/lib_dec/ivas_jbm_dec.c b/lib_dec/ivas_jbm_dec.c
index fd0375e7bef1a85e736a9e937af9997ec235f12e..7cc96cd14fb389a6cd94062d7da83121747335d5 100644
--- a/lib_dec/ivas_jbm_dec.c
+++ b/lib_dec/ivas_jbm_dec.c
@@ -783,7 +783,12 @@ ivas_error ivas_jbm_dec_render(
/* Rendering */
if ( st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV || st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV_ROOM )
{
- if ( ( error = ivas_rend_crendProcessSubframe( st_ivas->hCrendWrapper, st_ivas->intern_config, st_ivas->hOutSetup.output_config, st_ivas->hDecoderConfig, st_ivas->hHeadTrackData,
+ if ( ( error = ivas_rend_crendProcessSubframe( st_ivas->hCrendWrapper, st_ivas->intern_config, st_ivas->hOutSetup.output_config, st_ivas->hDecoderConfig,
+#ifdef EXTERNAL_ORIENTATIONS
+ st_ivas->hCombinedOrientationData,
+#else
+ st_ivas->hHeadTrackData,
+#endif
&st_ivas->hIntSetup, st_ivas->hEFAPdata, st_ivas->hTcBuffer, p_tc, p_output, *nSamplesRendered, output_Fs ) ) != IVAS_ERR_OK )
{
return error;
@@ -1005,8 +1010,13 @@ ivas_error ivas_jbm_dec_flush_renderer(
{
if ( renderer_type_old == RENDERER_BINAURAL_MIXER_CONV || renderer_type_old == RENDERER_BINAURAL_MIXER_CONV_ROOM )
{
- if ( ( error = ivas_rend_crendProcessSubframe( st_ivas->hCrendWrapper, intern_config_old, st_ivas->hOutSetup.output_config, st_ivas->hDecoderConfig, st_ivas->hHeadTrackData, hIntSetupOld,
- st_ivas->hEFAPdata, st_ivas->hTcBuffer, hTcBuffer->tc, p_output, hTcBuffer->n_samples_granularity, st_ivas->hDecoderConfig->output_Fs ) ) != IVAS_ERR_OK )
+ if ( ( error = ivas_rend_crendProcessSubframe( st_ivas->hCrendWrapper, intern_config_old, st_ivas->hOutSetup.output_config, st_ivas->hDecoderConfig,
+#ifdef EXTERNAL_ORIENTATIONS
+ st_ivas->hCombinedOrientationData,
+#else
+ st_ivas->hHeadTrackData,
+#endif
+ hIntSetupOld, st_ivas->hEFAPdata, st_ivas->hTcBuffer, hTcBuffer->tc, p_output, hTcBuffer->n_samples_granularity, st_ivas->hDecoderConfig->output_Fs ) ) != IVAS_ERR_OK )
{
return error;
}
diff --git a/lib_dec/ivas_mc_param_dec.c b/lib_dec/ivas_mc_param_dec.c
index 2745481402f25ba335f53f86157335e1ecfff714..78cdbfadc9e5d454b6c261b8a94c9c9ea90f01c0 100644
--- a/lib_dec/ivas_mc_param_dec.c
+++ b/lib_dec/ivas_mc_param_dec.c
@@ -424,8 +424,14 @@ ivas_error ivas_param_mc_dec_open(
ivas_param_mc_dec_compute_interpolator( 0, 0, DEFAULT_JBM_CLDFB_TIMESLOTS, hParamMC->h_output_synthesis_params.interpolator );
+
+#ifdef EXTERNAL_ORIENTATIONS
+ /* Head or external rotation */
+ if ( ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) && ( st_ivas->hDecoderConfig->Opt_Headrotation || st_ivas->hDecoderConfig->Opt_ExternalOrientation ) )
+#else
/* Head rotation */
if ( ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) && st_ivas->hDecoderConfig->Opt_Headrotation )
+#endif
{
if ( ( hParamMC->hoa_encoder = (float *) malloc( st_ivas->hTransSetup.nchan_out_woLFE * MAX_INTERN_CHANNELS * sizeof( float ) ) ) == NULL )
{
@@ -1748,7 +1754,11 @@ void ivas_param_mc_dec_render(
if ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM )
{
- ivas_binRenderer( st_ivas->hBinRenderer, st_ivas->hHeadTrackData, hParamMC->subframe_nbslots[subframe_idx],
+ ivas_binRenderer( st_ivas->hBinRenderer, st_ivas->hHeadTrackData,
+#ifdef EXTERNAL_ORIENTATIONS
+ st_ivas->hCombinedOrientationData, subframe_idx,
+#endif
+ hParamMC->subframe_nbslots[subframe_idx],
Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, Cldfb_RealBuffer, Cldfb_ImagBuffer );
}
else if ( hParamMC->synthesis_conf == PARAM_MC_SYNTH_LS_CONV_CLDFB )
diff --git a/lib_dec/ivas_objectRenderer_internal.c b/lib_dec/ivas_objectRenderer_internal.c
index df210f2f8a4e6e37b8c2f8a3a58499370c7e6c97..9ba6351f638d2ee0ad88003328f615a705ff278d 100644
--- a/lib_dec/ivas_objectRenderer_internal.c
+++ b/lib_dec/ivas_objectRenderer_internal.c
@@ -85,7 +85,13 @@ 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,
- st_ivas->hIsmMetaData, st_ivas->hDecoderConfig->Opt_Headrotation, ( st_ivas->hHeadTrackData != NULL ) ? st_ivas->hHeadTrackData->Quaternions : NULL,
+ st_ivas->hIsmMetaData,
+#ifdef EXTERNAL_ORIENTATIONS
+ ( st_ivas->hCombinedOrientationData != NULL ) ? st_ivas->hCombinedOrientationData->enableCombinedOrientation : NULL,
+ ( st_ivas->hCombinedOrientationData != NULL ) ? st_ivas->hCombinedOrientationData->Quaternions : NULL,
+#else
+ st_ivas->hDecoderConfig->Opt_Headrotation, ( st_ivas->hHeadTrackData != NULL ) ? st_ivas->hHeadTrackData->Quaternions : NULL,
+#endif
( st_ivas->hHeadTrackData != NULL ) ? st_ivas->hHeadTrackData->Pos : NULL, ism_md_subframe_update, output, output_frame );
}
@@ -175,8 +181,14 @@ ivas_error ivas_td_binaural_renderer_sf(
}
/* Update the listener's location/orientation */
- TDREND_Update_listener_orientation( st_ivas->hBinRendererTd, st_ivas->hDecoderConfig->Opt_Headrotation,
+ TDREND_Update_listener_orientation( st_ivas->hBinRendererTd,
+#ifdef EXTERNAL_ORIENTATIONS
+ ( st_ivas->hCombinedOrientationData != NULL ) ? st_ivas->hCombinedOrientationData->enableCombinedOrientation[subframe_idx] : 0,
+ ( st_ivas->hCombinedOrientationData != NULL ) ? st_ivas->hCombinedOrientationData->Quaternions : NULL,
+#else
+ st_ivas->hDecoderConfig->Opt_Headrotation,
( st_ivas->hHeadTrackData != NULL ) ? &st_ivas->hHeadTrackData->Quaternions[0] : NULL,
+#endif
( st_ivas->hHeadTrackData != NULL ) ? st_ivas->hHeadTrackData->Pos : NULL );
if ( ( st_ivas->hRenderConfig != NULL ) && ( st_ivas->hRenderConfig->roomAcoustics.late_reverb_on ) )
diff --git a/lib_dec/ivas_output_config.c b/lib_dec/ivas_output_config.c
index e4c389e2f33d75921e997a480b04c88b7e71af7b..07beb889968be231c6a0d091f43bccb43fc6aea9 100644
--- a/lib_dec/ivas_output_config.c
+++ b/lib_dec/ivas_output_config.c
@@ -191,9 +191,17 @@ void ivas_renderer_select(
if ( output_config == AUDIO_CONFIG_BINAURAL )
{
#ifdef DEBUGGING
+#ifdef EXTERNAL_ORIENTATIONS
+ if ( ( ( ( st_ivas->transport_config == AUDIO_CONFIG_5_1 || st_ivas->transport_config == AUDIO_CONFIG_7_1 ) && ( st_ivas->hDecoderConfig->Opt_Headrotation || st_ivas->hDecoderConfig->Opt_ExternalOrientation ) ) || ( st_ivas->hDecoderConfig->force_rend == FORCE_TD_RENDERER ) ) && ( st_ivas->mc_mode == MC_MODE_MCT || st_ivas->mc_mode == MC_MODE_PARAMUPMIX ) && !( st_ivas->hDecoderConfig->force_rend == FORCE_CLDFB_RENDERER ) )
+#else
if ( ( ( ( st_ivas->transport_config == AUDIO_CONFIG_5_1 || st_ivas->transport_config == AUDIO_CONFIG_7_1 ) && st_ivas->hDecoderConfig->Opt_Headrotation ) || ( st_ivas->hDecoderConfig->force_rend == FORCE_TD_RENDERER ) ) && ( st_ivas->mc_mode == MC_MODE_MCT || st_ivas->mc_mode == MC_MODE_PARAMUPMIX ) && !( st_ivas->hDecoderConfig->force_rend == FORCE_CLDFB_RENDERER ) )
+#endif
+#else
+#ifdef EXTERNAL_ORIENTATIONS
+ if ( ( st_ivas->transport_config == AUDIO_CONFIG_5_1 || st_ivas->transport_config == AUDIO_CONFIG_7_1 ) && ( st_ivas->hDecoderConfig->Opt_Headrotation || st_ivas->hDecoderConfig->Opt_ExternalOrientation ) && ( st_ivas->mc_mode == MC_MODE_MCT || st_ivas->mc_mode == MC_MODE_PARAMUPMIX ) )
#else
if ( ( st_ivas->transport_config == AUDIO_CONFIG_5_1 || st_ivas->transport_config == AUDIO_CONFIG_7_1 ) && st_ivas->hDecoderConfig->Opt_Headrotation && ( st_ivas->mc_mode == MC_MODE_MCT || st_ivas->mc_mode == MC_MODE_PARAMUPMIX ) )
+#endif
#endif
{
*renderer_type = RENDERER_BINAURAL_OBJECTS_TD;
@@ -219,7 +227,11 @@ void ivas_renderer_select(
*renderer_type = RENDERER_BINAURAL_FASTCONV;
}
#endif
+#ifdef EXTERNAL_ORIENTATIONS
+ if ( st_ivas->hDecoderConfig->Opt_Headrotation || st_ivas->hDecoderConfig->Opt_ExternalOrientation )
+#else
if ( st_ivas->hDecoderConfig->Opt_Headrotation )
+#endif
{
/* force HOA3 domain for rotation*/
*internal_config = AUDIO_CONFIG_HOA3;
diff --git a/lib_dec/ivas_stat_dec.h b/lib_dec/ivas_stat_dec.h
index ba8f573364026477612a08411093bb1cc819fca5..e63f6c3e43b9cbb38d0dad857509c47040c9132d 100644
--- a/lib_dec/ivas_stat_dec.h
+++ b/lib_dec/ivas_stat_dec.h
@@ -1187,6 +1187,9 @@ typedef struct decoder_config_structure
int16_t Opt_non_diegetic_pan; /* indicates diegetic or not */
float non_diegetic_pan_gain; /* non diegetic panning gain*/
int16_t Opt_AMR_WB; /* flag indicating AMR-WB IO mode */
+#ifdef EXTERNAL_ORIENTATIONS
+ int16_t Opt_ExternalOrientation; /* indiates whether external orientations are used */
+#endif
/* temp. development parameters */
#ifdef DEBUGGING
@@ -1305,6 +1308,10 @@ typedef struct Decoder_Struct
HEAD_TRACK_DATA_HANDLE hHeadTrackData; /* Head tracking data structure */
RENDER_CONFIG_DATA *hRenderConfig; /* Renderer config pointer */
int32_t binaural_latency_ns; /* Binauralization latency in ns */
+#ifdef EXTERNAL_ORIENTATIONS
+ EXTERNAL_ORIENTATION_HANDLE hExtOrientationData; /* External orientation data structure */
+ COMBINED_ORIENTATION_HANDLE hCombinedOrientationData; /* Combined external and head orientation data structure */
+#endif
/* JBM module */
DECODER_TC_BUFFER_HANDLE hTcBuffer; /* JBM structure */
diff --git a/lib_dec/lib_dec.c b/lib_dec/lib_dec.c
index 3b4618b6a29011fef488c547e9ec71457e4213dd..e01c59b77942f19c06f000da803c265122eb3a41 100644
--- a/lib_dec/lib_dec.c
+++ b/lib_dec/lib_dec.c
@@ -243,6 +243,10 @@ static void init_decoder_config(
hDecoderConfig->Opt_delay_comp = 0;
+#ifdef EXTERNAL_ORIENTATIONS
+ hDecoderConfig->Opt_ExternalOrientation = 0;
+#endif
+
return;
}
@@ -398,12 +402,15 @@ static IVAS_DEC_BS_FORMAT mapIvasFormat(
*---------------------------------------------------------------------*/
ivas_error IVAS_DEC_Configure(
- IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
- const uint32_t sampleRate, /* i : output sampling frequency */
- const IVAS_DEC_AUDIO_CONFIG outputFormat, /* i : output format */
- const int16_t customLsOutputEnabled, /* i : enable custom loudspeaker setup handle */
- const int16_t hrtfReaderEnabled, /* i : enable HRTF binary file input */
- const int16_t enableHeadRotation, /* i : enable head rotation for binaural output */
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ const uint32_t sampleRate, /* i : output sampling frequency */
+ const IVAS_DEC_AUDIO_CONFIG outputFormat, /* i : output format */
+ const int16_t customLsOutputEnabled, /* i : enable custom loudspeaker setup handle */
+ const int16_t hrtfReaderEnabled, /* i : enable HRTF binary file input */
+ const int16_t enableHeadRotation, /* i : enable head rotation for binaural output */
+#ifdef EXTERNAL_ORIENTATIONS
+ const int16_t enableExternalOrientation, /* i : enable external orientations */
+#endif
const HEAD_ORIENT_TRK_T orientation_tracking, /* i : head orientation tracking type */
const int16_t renderConfigEnabled, /* i : enable Renderer config. file for binaural output */
const int16_t Opt_non_diegetic_pan, /* i : diegetic or not */
@@ -463,6 +470,9 @@ ivas_error IVAS_DEC_Configure(
hDecoderConfig->Opt_non_diegetic_pan = Opt_non_diegetic_pan;
hDecoderConfig->non_diegetic_pan_gain = non_diegetic_pan_gain;
hDecoderConfig->Opt_delay_comp = delayCompensationEnabled;
+#ifdef EXTERNAL_ORIENTATIONS
+ hDecoderConfig->Opt_ExternalOrientation = enableExternalOrientation;
+#endif
/* Set decoder parameters to initial values */
if ( ( error = ivas_init_decoder_front( st_ivas ) ) != IVAS_ERR_OK )
@@ -1220,6 +1230,52 @@ ivas_error IVAS_DEC_FeedRefVectorData(
return ivas_orient_trk_SetReferenceVector( pOtr, listenerPos, refPos );
}
+#ifdef EXTERNAL_ORIENTATIONS
+/*---------------------------------------------------------------------*
+ * IVAS_DEC_FeedExternalOrientationData( )
+ *
+ * Feed the decoder with the external orientation data
+ *---------------------------------------------------------------------*/
+
+ivas_error IVAS_DEC_FeedExternalOrientationData(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ IVAS_QUATERNION *orientation, /* i : external orientation data */
+ int8_t *enableHeadRotation, /* i : flag to enable head rotation for this frame */
+ int8_t *enableExternalOrientation, /* i : flag to enable external orientation for this frame */
+ int8_t *enableRotationInterpolation, /* i : flag to interpolate rotations from current and previous frames */
+ int16_t *numFramesToTargetOrientation /* i : number of frames until target orientation is reached */
+)
+{
+ EXTERNAL_ORIENTATION_HANDLE hExternalOrientationData;
+ int16_t i;
+
+ if ( hIvasDec == NULL || hIvasDec->st_ivas == NULL || orientation == NULL )
+ {
+ return IVAS_ERR_UNEXPECTED_NULL_POINTER;
+ }
+
+ hExternalOrientationData = hIvasDec->st_ivas->hExtOrientationData;
+
+ if ( hExternalOrientationData == NULL )
+ {
+ return IVAS_ERR_UNEXPECTED_NULL_POINTER;
+ }
+
+ /* Move external orientation data to the decoder handle (invert orientations) */
+ for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
+ {
+ QuaternionInverse( orientation[i], &hExternalOrientationData->Quaternions[i] );
+
+ hExternalOrientationData->enableHeadRotation[i] = enableHeadRotation[i];
+ hExternalOrientationData->enableExternalOrientation[i] = enableExternalOrientation[i];
+ hExternalOrientationData->enableRotationInterpolation[i] = enableRotationInterpolation[i];
+ hExternalOrientationData->numFramesToTargetOrientation[i] = numFramesToTargetOrientation[i];
+ }
+
+ return IVAS_ERR_OK;
+}
+#endif
+
/*---------------------------------------------------------------------*
* IVAS_DEC_FeedCustomLsData( )
*
@@ -2509,6 +2565,13 @@ static ivas_error printConfigInfo_dec(
fprintf( stdout, "Head rotation: ON\n" );
}
+#ifdef EXTERNAL_ORIENTATIONS
+ if ( st_ivas->hDecoderConfig->Opt_ExternalOrientation )
+ {
+ fprintf( stdout, "External orientation: ON\n" );
+ }
+#endif
+
if ( st_ivas->hDecoderConfig->orientation_tracking != HEAD_ORIENT_TRK_NONE )
{
switch ( st_ivas->hDecoderConfig->orientation_tracking )
diff --git a/lib_dec/lib_dec.h b/lib_dec/lib_dec.h
index 0572ace82e3f7de7cd5bfec8c1f4f3890439434a..c5eb095bb12b5e478b0172b84adc3e63aabe74e2 100644
--- a/lib_dec/lib_dec.h
+++ b/lib_dec/lib_dec.h
@@ -143,10 +143,13 @@ ivas_error IVAS_DEC_Configure(
const int16_t customLsOutputEnabled, /* i : enable custom loudspeaker setup handle */
const int16_t hrtfReaderEnabled, /* i : enable HRTF binary file input */
const int16_t enableHeadRotation, /* i : enable head rotation for binaural output */
+#ifdef EXTERNAL_ORIENTATIONS
+ const int16_t enableExternalOrientation, /* i : enable external orientations */
+#endif
const HEAD_ORIENT_TRK_T orientation_tracking, /* i : head orientation tracking type */
const int16_t renderConfigEnabled, /* i : enable Renderer config. file for binaural output */
const int16_t Opt_non_diegetic_pan, /* i : diegetic or not */
- const float non_diegetic_pan_gain, /* i : non diegetic panning gain */
+ const float non_diegetic_pan_gain, /* i : non diegetic panning gain */
const int16_t delayCompensationEnabled /* i : enable delay compensation */
);
@@ -205,6 +208,18 @@ ivas_error IVAS_DEC_FeedRefVectorData(
const IVAS_VECTOR3 refPos /* i : Reference position */
);
+#ifdef EXTERNAL_ORIENTATIONS
+/*! r: error code */
+ivas_error IVAS_DEC_FeedExternalOrientationData(
+ IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
+ IVAS_QUATERNION *orientation, /* i : external orientation data */
+ int8_t *enableHeadRotation, /* i : flag to enable head rotation for this frame */
+ int8_t *enableExternalOrientation, /* i : flag to enable external orientation for this frame */
+ int8_t *enableRotationInterpolation, /* i : flag to interpolate rotations from current and previous frames */
+ int16_t *numFramesToTargetOrientation /* i : number of frames until target orientation is reached */
+);
+#endif
+
/*! r: error code */
ivas_error IVAS_DEC_VoIP_FeedFrame(
IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
diff --git a/lib_rend/ivas_crend.c b/lib_rend/ivas_crend.c
index 10f8743b230cce1a26c0255a5792acd6adfcd3a0..2b61fa7ef4aad927a010afcf6932224a9e41b960 100644
--- a/lib_rend/ivas_crend.c
+++ b/lib_rend/ivas_crend.c
@@ -1463,7 +1463,11 @@ ivas_error ivas_rend_crendProcess(
const AUDIO_CONFIG inConfig,
const AUDIO_CONFIG outConfig,
DECODER_CONFIG_HANDLE hDecoderConfig,
+#ifdef EXTERNAL_ORIENTATIONS
+ COMBINED_ORIENTATION_HANDLE hCombinedOrientationData,
+#else
HEAD_TRACK_DATA_HANDLE hHeadTrackData,
+#endif
IVAS_OUTPUT_SETUP_HANDLE hIntSetup,
EFAP_HANDLE hEFAPdata,
float *output[], /* i/o: input/output audio channels */
@@ -1478,6 +1482,22 @@ ivas_error ivas_rend_crendProcess(
ivas_error error;
IVAS_REND_AudioConfig inRendConfig;
IVAS_REND_AudioConfig outRendConfig;
+#ifdef EXTERNAL_ORIENTATIONS
+ int8_t combinedOrientationEnabled;
+
+ combinedOrientationEnabled = 0;
+ if ( hCombinedOrientationData != NULL )
+ {
+ for ( subframe_idx = 0; subframe_idx < MAX_PARAM_SPATIAL_SUBFRAMES; subframe_idx++ )
+ {
+ if ( hCombinedOrientationData->enableCombinedOrientation[subframe_idx] != 0 )
+ {
+ combinedOrientationEnabled = 1;
+ break;
+ }
+ }
+ }
+#endif
push_wmops( "ivas_rend_crendProcess" );
@@ -1503,7 +1523,11 @@ ivas_error ivas_rend_crendProcess(
for ( subframe_idx = 0; subframe_idx < MAX_PARAM_SPATIAL_SUBFRAMES; subframe_idx++ )
{
+#ifdef EXTERNAL_ORIENTATIONS
+ if ( hDecoderConfig && combinedOrientationEnabled )
+#else
if ( hDecoderConfig && hDecoderConfig->Opt_Headrotation && hHeadTrackData && hHeadTrackData->num_quaternions >= 0 )
+#endif
{
/* Orientation tracking */
@@ -1513,12 +1537,20 @@ ivas_error ivas_rend_crendProcess(
*/
if ( in_config == AUDIO_CONFIG_FOA || in_config == AUDIO_CONFIG_HOA2 || in_config == AUDIO_CONFIG_HOA3 )
{
+#ifdef EXTERNAL_ORIENTATIONS
+ rotateFrame_shd( hCombinedOrientationData, output, subframe_len, *hIntSetup, subframe_idx );
+#else
rotateFrame_shd( hHeadTrackData, output, subframe_len, *hIntSetup, subframe_idx );
+#endif
}
/* Rotation in SD for MC -> BINAURAL_ROOM */
else if ( ( hIntSetup != NULL ) && hIntSetup->is_loudspeaker_setup )
{
+#ifdef EXTERNAL_ORIENTATIONS
+ rotateFrame_sd( hCombinedOrientationData, output, subframe_len, *hIntSetup, hEFAPdata, subframe_idx );
+#else
rotateFrame_sd( hHeadTrackData, output, subframe_len, *hIntSetup, hEFAPdata, subframe_idx );
+#endif
}
}
@@ -1562,18 +1594,22 @@ ivas_error ivas_rend_crendProcess(
*-----------------------------------------------------------------------------------------*/
ivas_error ivas_rend_crendProcessSubframe(
- const CREND_WRAPPER *pCrend, /* i/o: Crend wrapper handle */
- const AUDIO_CONFIG inConfig, /* i : input audio configuration */
- const AUDIO_CONFIG outConfig, /* i : output audio configuration */
- const DECODER_CONFIG_HANDLE hDecoderConfig, /* i : decoder config. structure */
+ const CREND_WRAPPER *pCrend, /* i/o: Crend wrapper handle */
+ const AUDIO_CONFIG inConfig, /* i : input audio configuration */
+ const AUDIO_CONFIG outConfig, /* i : output audio configuration */
+ const DECODER_CONFIG_HANDLE hDecoderConfig, /* i : decoder config. structure */
+#ifdef EXTERNAL_ORIENTATIONS
+ const COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, /* i : combined orientation handle */
+#else
const HEAD_TRACK_DATA_HANDLE hHeadTrackData, /* i : Head tracking data structure */
- const IVAS_OUTPUT_SETUP_HANDLE hIntSetup, /* i : internal setup handle */
- const EFAP_HANDLE hEFAPdata, /* i : EFAP handle */
- DECODER_TC_BUFFER_HANDLE hTcBuffer, /* i/o: JBM handle */
- float *input_f[], /* i : transport channels */
- float *output[], /* i/o: input/output audio channels */
- const int16_t n_samples_to_render, /* i : output frame length per channel */
- const int32_t output_Fs /* i : output sampling rate */
+#endif
+ const IVAS_OUTPUT_SETUP_HANDLE hIntSetup, /* i : internal setup handle */
+ const EFAP_HANDLE hEFAPdata, /* i : EFAP handle */
+ DECODER_TC_BUFFER_HANDLE hTcBuffer, /* i/o: JBM handle */
+ float *input_f[], /* i : transport channels */
+ float *output[], /* i/o: input/output audio channels */
+ const int16_t n_samples_to_render, /* i : output frame length per channel */
+ const int32_t output_Fs /* i : output sampling rate */
)
{
int16_t subframe_idx, subframe_len;
@@ -1586,6 +1622,22 @@ ivas_error ivas_rend_crendProcessSubframe(
ivas_error error;
IVAS_REND_AudioConfig inRendConfig;
IVAS_REND_AudioConfig outRendConfig;
+#ifdef EXTERNAL_ORIENTATIONS
+ int8_t combinedOrientationEnabled;
+
+ combinedOrientationEnabled = 0;
+ if ( hCombinedOrientationData != NULL )
+ {
+ for ( subframe_idx = 0; subframe_idx < MAX_PARAM_SPATIAL_SUBFRAMES; subframe_idx++ )
+ {
+ if ( hCombinedOrientationData->enableCombinedOrientation[subframe_idx] != 0 )
+ {
+ combinedOrientationEnabled = 1;
+ break;
+ }
+ }
+ }
+#endif
push_wmops( "ivas_rend_crendProcessSubframe" );
@@ -1633,7 +1685,11 @@ ivas_error ivas_rend_crendProcessSubframe(
{
subframe_len = hTcBuffer->subframe_nbslots[subframe_idx] * hTcBuffer->n_samples_granularity;
+#ifdef EXTERNAL_ORIENTATIONS
+ if ( hDecoderConfig && combinedOrientationEnabled )
+#else
if ( hDecoderConfig && hDecoderConfig->Opt_Headrotation && hHeadTrackData && hHeadTrackData->num_quaternions >= 0 )
+#endif
{
/* Rotation in SHD for:
MC with elevation (5_1_2 / 5_1_4 / 7_1_4) -> BINAURAL
@@ -1641,12 +1697,24 @@ ivas_error ivas_rend_crendProcessSubframe(
*/
if ( in_config == AUDIO_CONFIG_FOA || in_config == AUDIO_CONFIG_HOA2 || in_config == AUDIO_CONFIG_HOA3 )
{
- rotateFrame_shd( hHeadTrackData, tc_local, subframe_len, *hIntSetup, 0 );
+ rotateFrame_shd(
+#ifdef EXTERNAL_ORIENTATIONS
+ hCombinedOrientationData,
+#else
+ hHeadTrackData,
+#endif
+ tc_local, subframe_len, *hIntSetup, 0 );
}
/* Rotation in SD for MC -> BINAURAL_ROOM */
else if ( ( hIntSetup != NULL ) && hIntSetup->is_loudspeaker_setup )
{
- rotateFrame_sd( hHeadTrackData, tc_local, subframe_len, *hIntSetup, hEFAPdata, 0 );
+ rotateFrame_sd(
+#ifdef EXTERNAL_ORIENTATIONS
+ hCombinedOrientationData,
+#else
+ hHeadTrackData,
+#endif
+ tc_local, subframe_len, *hIntSetup, hEFAPdata, 0 );
}
}
diff --git a/lib_rend/ivas_dirac_dec_binaural_functions.c b/lib_rend/ivas_dirac_dec_binaural_functions.c
index 2e4dbbabcb0238b9ff88a298e8fdc6ce0145a3ef..2eefb0e1d388c07bc52d166bd2e03592cab3719a 100644
--- a/lib_rend/ivas_dirac_dec_binaural_functions.c
+++ b/lib_rend/ivas_dirac_dec_binaural_functions.c
@@ -81,7 +81,14 @@ typedef struct hrtfGainCache
* Local function prototypes
*------------------------------------------------------------------------*/
-static void ivas_dirac_dec_binaural_internal( Decoder_Struct *st_ivas, float *output_f[], const int16_t nchan_transport, const int16_t subframe );
+static void ivas_dirac_dec_binaural_internal( Decoder_Struct *st_ivas,
+#ifdef EXTERNAL_ORIENTATIONS
+ COMBINED_ORIENTATION_HANDLE hCombinedOrientationData,
+#endif
+ float *output_f[],
+ const int16_t nchan_transport,
+ const int16_t subframe );
+
static void ivas_dirac_dec_decorrelate_slot( DIRAC_DEC_HANDLE hDirAC, const int16_t slot, float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float decRe[][CLDFB_NO_CHANNELS_MAX], float decIm[][CLDFB_NO_CHANNELS_MAX] );
#ifdef FIX_511_OPTIMIZE_PARAMBIN_GAIN_FETCH
@@ -96,9 +103,29 @@ static void ivas_dirac_dec_binaural_determine_processing_matrices( Decoder_Struc
static void ivas_dirac_dec_binaural_process_output( Decoder_Struct *st_ivas, float *output_f[], float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], const int16_t max_band_decorr, const int16_t numInChannels, const int16_t subframe );
-static void adaptTransportSignalsHeadtracked( HEAD_TRACK_DATA_HANDLE hHeadTrackData, float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], const int16_t nBins, const int16_t nSlots, float Rmat[3][3] );
+static void adaptTransportSignalsHeadtracked(
+#ifdef EXTERNAL_ORIENTATIONS
+ COMBINED_ORIENTATION_HANDLE hHeadTrackData,
+#else
+ HEAD_TRACK_DATA_HANDLE hHeadTrackData,
+#endif
+ float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
+ float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
+ const int16_t nBins,
+ const int16_t nSlots,
+ float Rmat[3][3] );
-static void ivas_dirac_dec_binaural_check_and_switch_transports_headtracked( HEAD_TRACK_DATA_HANDLE hHeadTrackData, float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], const int16_t nBins, const int16_t nSlots, float Rmat[3][3] );
+static void ivas_dirac_dec_binaural_check_and_switch_transports_headtracked(
+#ifdef EXTERNAL_ORIENTATIONS
+ COMBINED_ORIENTATION_HANDLE hHeadTrackData,
+#else
+ HEAD_TRACK_DATA_HANDLE hHeadTrackData,
+#endif
+ float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
+ float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
+ const int16_t nBins,
+ const int16_t nSlots,
+ float Rmat[3][3] );
static void formulate2x2MixingMatrix( float Ein1, float Ein2, float CinRe, float CinIm, float Eout1, float Eout2, float CoutRe, float CoutIm, float Q[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float Mre[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float Mim[BINAURAL_CHANNELS][BINAURAL_CHANNELS], const float regularizationFactor );
#ifdef FIX_511_OPTIMIZE_PARAMBIN_GAIN_FETCH
@@ -387,7 +414,7 @@ void ivas_dirac_dec_binaural_render(
for ( subframe_idx = first_sf; subframe_idx < last_sf; subframe_idx++ )
{
int16_t n_samples_sf = slot_size * hDirAC->subframe_nbslots[subframe_idx];
- ivas_dirac_dec_binaural_internal( st_ivas, output_f_local, nchan_transport, subframe_idx );
+ ivas_dirac_dec_binaural_internal( st_ivas, st_ivas->hCombinedOrientationData, output_f_local, nchan_transport, subframe_idx );
for ( ch = 0; ch < nchan_out; ch++ )
{
output_f_local[ch] += n_samples_sf;
@@ -412,7 +439,10 @@ void ivas_dirac_dec_binaural_render(
*------------------------------------------------------------------------*/
void ivas_dirac_dec_binaural(
- Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */
+ Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */
+#ifdef EXTERNAL_ORIENTATIONS
+ COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, /* i : combined orientation handle */
+#endif
float output_f[][L_FRAME48k], /* i/o: synthesized core-coder transport channels/DirAC output */
const int16_t nchan_transport /* i : number of transport channels */
)
@@ -471,7 +501,11 @@ void ivas_dirac_dec_binaural(
{
int16_t n_samples_sf = slot_size * st_ivas->hDirAC->subframe_nbslots[subframe];
+#ifdef EXTERNAL_ORIENTATIONS
+ ivas_dirac_dec_binaural_internal( st_ivas, hCombinedOrientationData, p_output, nchan_transport, subframe );
+#else
ivas_dirac_dec_binaural_internal( st_ivas, p_output, nchan_transport, subframe );
+#endif
for ( ch = 0; ch < 2 * BINAURAL_CHANNELS; ch++ )
{
@@ -496,6 +530,9 @@ void ivas_dirac_dec_binaural(
static void ivas_dirac_dec_binaural_internal(
Decoder_Struct *st_ivas,
+#ifdef EXTERNAL_ORIENTATIONS
+ COMBINED_ORIENTATION_HANDLE hCombinedOrientationData,
+#endif
float *output_f[],
const int16_t nchan_transport,
const int16_t subframe )
@@ -508,6 +545,9 @@ static void ivas_dirac_dec_binaural_internal(
int16_t max_band_decorr;
DIFFUSE_DISTRIBUTION_DATA diffuseDistData;
int16_t nBins, offsetSamples;
+#ifdef EXTERNAL_ORIENTATIONS
+ int16_t i, j;
+#endif
hDirAC = st_ivas->hDirAC;
nBins = hDirAC->num_freq_bands;
@@ -640,6 +680,24 @@ static void ivas_dirac_dec_binaural_internal(
ivas_sba_prototype_renderer( st_ivas, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, subframe );
}
+#ifdef EXTERNAL_ORIENTATIONS
+ if ( hCombinedOrientationData )
+ {
+ for ( i = 0; i < 3; i++ )
+ {
+ for ( j = 0; j < 3; j++ )
+ {
+ Rmat[i][j] = hCombinedOrientationData->Rmat[subframe][i][j];
+ }
+ }
+
+ if ( nchan_transport == 2 )
+ {
+ adaptTransportSignalsHeadtracked( hCombinedOrientationData, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, nBins, hDirAC->subframe_nbslots[subframe], Rmat );
+
+ ivas_dirac_dec_binaural_check_and_switch_transports_headtracked( hCombinedOrientationData, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, nBins, hDirAC->subframe_nbslots[subframe], Rmat );
+ }
+#else
if ( st_ivas->hHeadTrackData && st_ivas->hHeadTrackData->num_quaternions >= 0 )
{
QuatToRotMat( st_ivas->hHeadTrackData->Quaternions[subframe], Rmat );
@@ -650,6 +708,7 @@ static void ivas_dirac_dec_binaural_internal(
ivas_dirac_dec_binaural_check_and_switch_transports_headtracked( st_ivas->hHeadTrackData, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, nBins, hDirAC->subframe_nbslots[subframe], Rmat );
}
+#endif
}
#ifdef FIX_511_OPTIMIZE_PARAMBIN_GAIN_FETCH
@@ -1476,7 +1535,11 @@ static void ivas_dirac_dec_binaural_process_output(
static void adaptTransportSignalsHeadtracked(
+#ifdef EXTERNAL_ORIENTATIONS
+ COMBINED_ORIENTATION_HANDLE hHeadTrackData,
+#else
HEAD_TRACK_DATA_HANDLE hHeadTrackData,
+#endif
float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
const int16_t nBins,
@@ -1591,7 +1654,11 @@ static void adaptTransportSignalsHeadtracked(
}
static void ivas_dirac_dec_binaural_check_and_switch_transports_headtracked(
+#ifdef EXTERNAL_ORIENTATIONS
+ COMBINED_ORIENTATION_HANDLE hHeadTrackData,
+#else
HEAD_TRACK_DATA_HANDLE hHeadTrackData,
+#endif
float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
const int16_t nBins,
diff --git a/lib_rend/ivas_objectRenderer.c b/lib_rend/ivas_objectRenderer.c
index 4d324e60f36c5526f52f50dd90310cdbbc1b7ece..c0eeb1ef74723006adc2045373e3108991b69340 100644
--- a/lib_rend/ivas_objectRenderer.c
+++ b/lib_rend/ivas_objectRenderer.c
@@ -260,12 +260,16 @@ ivas_error ivas_td_binaural_renderer_unwrap(
const int16_t lfe_idx, /* i : LFE channel index */
const IVAS_FORMAT ivas_format, /* i : IVAS format */
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 */
- const IVAS_VECTOR3 *Pos, /* i : Listener position data per subframe */
- const int16_t ism_md_subframe_update, /* i: Number of subframes to delay ism metadata to sync with audio */
- float *output[], /* i/o: SCE channels / Binaural synthesis */
- const int16_t output_frame /* i : output frame length */
+#ifdef EXTERNAL_ORIENTATIONS
+ const int16_t *enableCombinedOrientation, /* i : Combined orientation flag */
+#else
+ const int16_t Opt_Headrotation, /* i : Head rotation flag */
+#endif
+ const IVAS_QUATERNION *Quaternions, /* i : Head tracking data per subframe */
+ const IVAS_VECTOR3 *Pos, /* i : Listener position data per subframe */
+ const int16_t ism_md_subframe_update, /* i: Number of subframes to delay ism metadata to sync with audio */
+ float *output[], /* i/o: SCE channels / Binaural synthesis */
+ const int16_t output_frame /* i : output frame length */
)
{
int16_t subframe_length;
@@ -302,7 +306,11 @@ ivas_error ivas_td_binaural_renderer_unwrap(
TDREND_Update_object_positions( hBinRendererTd, num_src, ivas_format, hIsmMetaData );
}
/* Update the listener's location/orientation */
+#ifdef EXTERNAL_ORIENTATIONS
+ TDREND_Update_listener_orientation( hBinRendererTd, ( enableCombinedOrientation != NULL ) ? enableCombinedOrientation[subframe_idx] : 0, ( 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, ( Pos != NULL ) ? &Pos[subframe_idx] : NULL );
+#endif
if ( hReverb != NULL && hReverb->pConfig.roomAcoustics.late_reverb_on )
{
@@ -517,10 +525,27 @@ void TDREND_Update_listener_orientation(
UpVec[0] = Rmat[2][0];
UpVec[1] = Rmat[2][1];
UpVec[2] = Rmat[2][2];
+#ifdef EXTERNAL_ORIENTATIONS
+ if ( Pos != NULL )
+ {
+ /* Input position */
+ Pos_p[0] = ( *Pos ).x;
+ Pos_p[1] = ( *Pos ).y;
+ Pos_p[2] = ( *Pos ).z;
+ }
+ else
+ {
+ /* Listener at the origin */
+ Pos_p[0] = 0.0f;
+ Pos_p[1] = 0.0f;
+ Pos_p[2] = 0.0f;
+ }
+#else
/* Input position */
Pos_p[0] = ( *Pos ).x;
Pos_p[1] = ( *Pos ).y;
Pos_p[2] = ( *Pos ).z;
+#endif
}
else
{
@@ -600,10 +625,13 @@ ivas_error ivas_td_binaural_open_ext(
*---------------------------------------------------------------------*/
ivas_error ivas_td_binaural_renderer_ext(
- const TDREND_WRAPPER *pTDRend, /* i : TD Renderer wrapper structure */
- const IVAS_REND_AudioConfig inConfig, /* i : Input audio configuration */
- const LSSETUP_CUSTOM_STRUCT *customLsInput, /* i : Input custom loudspeaker layout */
- const IVAS_REND_HeadRotData *headRotData, /* i : Input head positions */
+ const TDREND_WRAPPER *pTDRend, /* i : TD Renderer wrapper structure */
+ const IVAS_REND_AudioConfig inConfig, /* i : Input audio configuration */
+ const LSSETUP_CUSTOM_STRUCT *customLsInput, /* i : Input custom loudspeaker layout */
+ const IVAS_REND_HeadRotData *headRotData, /* i : Input head positions */
+#ifdef EXTERNAL_ORIENTATIONS
+ const COMBINED_ORIENTATION_HANDLE *hCombinedOrientationData, /* i : Combined head and external orientations */
+#endif
const IVAS_REND_AudioObjectPosition *currentPos, /* i : Object position */
const REVERB_HANDLE hReverb, /* i : Reverberator handle */
const int16_t output_frame, /* i : output frame length */
@@ -665,8 +693,14 @@ ivas_error ivas_td_binaural_renderer_ext(
hIsmMetaData[0]->non_diegetic_flag = currentPos->non_diegetic_flag;
}
- if ( ( error = ivas_td_binaural_renderer_unwrap( hReverb, transport_config, pTDRend->hBinRendererTd, num_src, lfe_idx, ivas_format, hIsmMetaData, headRotData->headRotEnabled,
+ if ( ( error = ivas_td_binaural_renderer_unwrap( hReverb, transport_config, pTDRend->hBinRendererTd, num_src, lfe_idx, ivas_format, hIsmMetaData,
+#ifdef EXTERNAL_ORIENTATIONS
+ ( hCombinedOrientationData != NULL ) ? ( *hCombinedOrientationData )->enableCombinedOrientation : NULL,
+ ( hCombinedOrientationData != NULL ) ? ( *hCombinedOrientationData )->Quaternions : NULL,
+#else
+ headRotData->headRotEnabled,
( headRotData != NULL ) ? headRotData->headPositions : NULL,
+#endif
( headRotData != NULL ) ? headRotData->Pos : NULL, ism_md_subframe_update_ext, p_output, output_frame ) ) != IVAS_ERR_OK )
{
return error;
diff --git a/lib_rend/ivas_orient_trk.c b/lib_rend/ivas_orient_trk.c
index e05c8061dd406a900bcb5836f8386e3080f6c2cb..3843c48fc32097235e1ed3a6ea2496f5462ccdfe 100644
--- a/lib_rend/ivas_orient_trk.c
+++ b/lib_rend/ivas_orient_trk.c
@@ -81,7 +81,11 @@ static IVAS_QUATERNION IdentityQuaternion(
* Quaternion product
*------------------------------------------------------------------------------------------*/
+#ifdef EXTERNAL_ORIENTATIONS
+void QuaternionProduct(
+#else
static void QuaternionProduct(
+#endif
const IVAS_QUATERNION q1,
const IVAS_QUATERNION q2,
IVAS_QUATERNION *const r )
@@ -153,7 +157,11 @@ static void QuaternionNormalize(
* Computes a spherical linear interpolation between two quaternions
*------------------------------------------------------------------------------------------*/
+#ifdef EXTERNAL_ORIENTATIONS
+void QuaternionSlerp(
+#else
static void QuaternionSlerp(
+#endif
const IVAS_QUATERNION q1,
const IVAS_QUATERNION q2,
const float t,
@@ -231,7 +239,11 @@ static float QuaternionAngle(
* Computes an inverse quaternion
*------------------------------------------------------------------------------------------*/
+#ifdef EXTERNAL_ORIENTATIONS
+void QuaternionInverse(
+#else
static void QuaternionInverse(
+#endif
const IVAS_QUATERNION q,
IVAS_QUATERNION *const r )
{
diff --git a/lib_rend/ivas_prot_rend.h b/lib_rend/ivas_prot_rend.h
index e1328ca9d39c67b55bc21140c93dd854e95a3f1c..f34cee66d013cccf1e80f059c106d49829c7fa97 100644
--- a/lib_rend/ivas_prot_rend.h
+++ b/lib_rend/ivas_prot_rend.h
@@ -151,6 +151,9 @@ ivas_error ivas_sba_get_hoa_dec_matrix(
void ivas_dirac_dec_binaural(
Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */
+#ifdef EXTERNAL_ORIENTATIONS
+ COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, /* i : combined orientation handle */
+#endif
float output_f[][L_FRAME48k], /* i/o: synthesized core-coder transport channels/DirAC output */
const int16_t nchan_transport /* i : number of transport channels */
);
@@ -227,7 +230,11 @@ ivas_error ivas_td_binaural_renderer_unwrap(
const int16_t lfe_idx, /* i : LFE channel index */
const IVAS_FORMAT ivas_format, /* i : IVAS format */
ISM_METADATA_HANDLE *hIsmMetaData, /* i : ISM metadata handle */
+#ifdef EXTERNAL_ORIENTATIONS
+ const int16_t *enableCombinedOrientation, /* i : Combined orientation flag */
+#else
const int16_t Opt_Headrotation, /* i : Head rotation flag */
+#endif
const IVAS_QUATERNION *Quaternions, /* i : Head tracking data per subframe */
const IVAS_VECTOR3 *Pos, /* i : Listener position data per subframe */
const int16_t ism_md_subframe_update,
@@ -240,6 +247,9 @@ ivas_error ivas_td_binaural_renderer_ext(
const IVAS_REND_AudioConfig inConfig, /* i : Input audio configuration */
const LSSETUP_CUSTOM_STRUCT *customLsInput, /* i : Input custom loudspeaker layout */
const IVAS_REND_HeadRotData *headRotData, /* i : Input head positions */
+#ifdef EXTERNAL_ORIENTATIONS
+ const COMBINED_ORIENTATION_HANDLE *hCombinedOrientationData, /* i : Combined head and external orientations */
+#endif
const IVAS_REND_AudioObjectPosition *currentPos, /* i : Object position */
const REVERB_HANDLE hReverb, /* i : Reverberator handle */
const int16_t output_frame, /* i : output frame length */
@@ -492,7 +502,7 @@ void ivas_rend_closeCrend(
CREND_WRAPPER_HANDLE *pCrend );
ivas_error ivas_rend_initCrendWrapper(
- CREND_WRAPPER_HANDLE *pCrend
+ CREND_WRAPPER_HANDLE *pCrend
);
ivas_error ivas_rend_crendProcess(
@@ -500,11 +510,15 @@ ivas_error ivas_rend_crendProcess(
const AUDIO_CONFIG inConfig,
const AUDIO_CONFIG outConfig,
DECODER_CONFIG_HANDLE hDecoderConfig,
+#ifdef EXTERNAL_ORIENTATIONS
+ COMBINED_ORIENTATION_HANDLE hCombinedOrientationData,
+#else
HEAD_TRACK_DATA_HANDLE hHeadTrackData,
+#endif
IVAS_OUTPUT_SETUP_HANDLE hIntSetup,
EFAP_HANDLE hEFAPdata,
float *output[], /* i/o: input/output audio channels */
- const int32_t output_Fs
+ const int32_t output_Fs
);
ivas_error ivas_rend_crendProcessSubframe(
@@ -512,7 +526,11 @@ ivas_error ivas_rend_crendProcessSubframe(
const AUDIO_CONFIG inConfig, /* i : input audio configuration */
const AUDIO_CONFIG outConfig, /* i : output audio configuration */
const DECODER_CONFIG_HANDLE hDecoderConfig, /* i : decoder config. structure */
+#ifdef EXTERNAL_ORIENTATIONS
+ const COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, /* i : combined orientation handle */
+#else
const HEAD_TRACK_DATA_HANDLE hHeadTrackData, /* i : Head tracking data structure */
+#endif
const IVAS_OUTPUT_SETUP_HANDLE hIntSetup, /* i : internal setup handle */
const EFAP_HANDLE hEFAPdata, /* i : EFAP handle */
DECODER_TC_BUFFER_HANDLE hTcBuffer, /* i/o: JBM handle */
@@ -792,7 +810,11 @@ void SHrotmatgen(
);
void rotateFrame_shd(
+#ifdef EXTERNAL_ORIENTATIONS
+ COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, /* i : head and external orientation combined handle */
+#else
HEAD_TRACK_DATA_HANDLE hHeadTrackData, /* i : head track handle */
+#endif
float *output[], /* i/o: unrotated HOA3 signal buffer in TD */
const int16_t subframe_len, /* i : subframe length per channel */
const IVAS_OUTPUT_SETUP hTransSetup, /* i : format for rotation */
@@ -800,7 +822,11 @@ void rotateFrame_shd(
);
void rotateFrame_sd(
+#ifdef EXTERNAL_ORIENTATIONS
+ COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, /* i : head and external orientation combined handle */
+#else
HEAD_TRACK_DATA_HANDLE hHeadTrackData, /* i : head track handle */
+#endif
float *output[], /* i/o: unrotated SD signal buffer in TD */
const int16_t subframe_len, /* i : subframe length per channel */
const IVAS_OUTPUT_SETUP hTransSetup, /* i : format for rotation */
@@ -818,7 +844,11 @@ void rotateFrame_shd_cldfb(
);
void rotateFrame_sd_cldfb(
+#ifdef EXTERNAL_ORIENTATIONS
+ float Rmat[3][3], /* i : real-space rotation matrix */
+#else
HEAD_TRACK_DATA_HANDLE hHeadTrackData, /* i : head track handle */
+#endif
float Cldfb_RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i/o: unrotated HOA3 signal buffer in cldfb domain real part */
float Cldfb_ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i/o: unrotated HOA3 signal buffer in cldfb domain imag part */
const IVAS_OUTPUT_SETUP_HANDLE hOutputSetup, /* i : output format setup number of channels */
@@ -827,6 +857,54 @@ void rotateFrame_sd_cldfb(
const int16_t nb_band /* i : number of CLDFB bands to process */
);
+#ifdef EXTERNAL_ORIENTATIONS
+ivas_error ivas_external_orientation_open(
+ EXTERNAL_ORIENTATION_HANDLE *hExtOrientationData /* o : external orientation handle */
+);
+
+void ivas_external_orientation_close(
+ EXTERNAL_ORIENTATION_HANDLE *hExtOrientationData /* i/o: external orientation handle */
+);
+
+ivas_error ivas_combined_orientation_open(
+ COMBINED_ORIENTATION_HANDLE *hCombinedOrientationData /* o : combined orientation handle */
+);
+
+void ivas_combined_orientation_close(
+ COMBINED_ORIENTATION_HANDLE *hCombinedOrientationData /* i/o: combined orientation handle */
+);
+
+ivas_error combine_external_and_head_orientations_dec(
+ HEAD_TRACK_DATA_HANDLE hHeadTrackData, /* i : head track handle */
+ EXTERNAL_ORIENTATION_HANDLE hExtOrientationData, /* i : external orientation handle */
+ COMBINED_ORIENTATION_HANDLE hCombinedOrientationData /* i/o: combined orientation handle */
+);
+
+ivas_error combine_external_and_head_orientations_rend(
+ IVAS_REND_HeadRotData *hHeadTrackData, /* i : head track handle */
+ EXTERNAL_ORIENTATION_HANDLE hExtOrientationData, /* i : external orientation handle */
+ COMBINED_ORIENTATION_HANDLE hCombinedOrientationData /* i/o: combined orientation handle */
+);
+
+ivas_error combine_external_and_head_orientations(
+ IVAS_QUATERNION *headRotQuaternions, /* i : quaternions for head rotation */
+ int16_t numHeadRotQuaternions, /* i : number of head rotation quaternions */
+ EXTERNAL_ORIENTATION_HANDLE hExtOrientationData, /* i : external orientation handle */
+ COMBINED_ORIENTATION_HANDLE hCombinedOrientationData /* i/o: combined orientation handle */
+);
+
+void external_target_interpolation(
+ EXTERNAL_ORIENTATION_HANDLE hExtOrientationData, /* i : external orientation handle */
+ COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, /* i/o: combined orientation handle */
+ const int16_t i
+);
+
+bool are_orientations_same(
+ const IVAS_QUATERNION *orientation1,
+ const IVAS_QUATERNION *orientation2
+);
+#endif
+
/*----------------------------------------------------------------------------------*
* Renderer configuration
@@ -846,6 +924,31 @@ ivas_error ivas_render_config_init_from_rom(
);
+#ifdef EXTERNAL_ORIENTATIONS
+/*----------------------------------------------------------------------------------*
+ * Quaternion operations
+ *----------------------------------------------------------------------------------*/
+
+void QuaternionProduct(
+ const IVAS_QUATERNION q1,
+ const IVAS_QUATERNION q2,
+ IVAS_QUATERNION *const r
+);
+
+void QuaternionInverse(
+ const IVAS_QUATERNION q,
+ IVAS_QUATERNION *const r
+);
+
+void QuaternionSlerp(
+ const IVAS_QUATERNION q1,
+ const IVAS_QUATERNION q2,
+ const float t,
+ IVAS_QUATERNION *const r
+);
+#endif
+
+
/*----------------------------------------------------------------------------------*
* Orientation tracking
*----------------------------------------------------------------------------------*/
diff --git a/lib_rend/ivas_rotation.c b/lib_rend/ivas_rotation.c
index 2ae0347fd38164b50f0c5f917c2fc0d7db86a7f1..7ab33cec891bf979719f71f987270f3b4b217dc5 100644
--- a/lib_rend/ivas_rotation.c
+++ b/lib_rend/ivas_rotation.c
@@ -249,11 +249,15 @@ void rotateAziEle(
*------------------------------------------------------------------------*/
void rotateFrame_shd(
+#ifdef EXTERNAL_ORIENTATIONS
+ COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, /* i : head and external orientation combined handle */
+#else
HEAD_TRACK_DATA_HANDLE hHeadTrackData, /* i : head track handle */
- float *output[], /* i/o: unrotated HOA3 signal buffer in TD */
- const int16_t subframe_len, /* i : subframe length per channel */
- const IVAS_OUTPUT_SETUP hTransSetup, /* i : format for rotation */
- const int16_t subframe_idx /* i : subframe index */
+#endif
+ float *output[], /* i/o: unrotated HOA3 signal buffer in TD */
+ const int16_t subframe_len, /* i : subframe length per channel */
+ const IVAS_OUTPUT_SETUP hTransSetup, /* i : format for rotation */
+ const int16_t subframe_idx /* i : subframe index */
)
{
int16_t i, l, n, m;
@@ -281,12 +285,19 @@ void rotateFrame_shd(
set_zero( SHrotmat[i], HEADROT_SHMAT_DIM );
}
+#ifndef EXTERNAL_ORIENTATIONS
/* get next quaternion */
QuatToRotMat( hHeadTrackData->Quaternions[hHeadTrackData->num_quaternions++], hHeadTrackData->Rmat );
+#endif
/* calculate ambisonics rotation matrices for the previous and current frames */
+#ifdef EXTERNAL_ORIENTATIONS
+ SHrotmatgen( SHrotmat_prev, hCombinedOrientationData->Rmat_prev, shd_rot_max_order );
+ SHrotmatgen( SHrotmat, hCombinedOrientationData->Rmat[subframe_idx], shd_rot_max_order );
+#else
SHrotmatgen( SHrotmat_prev, hHeadTrackData->Rmat_prev, shd_rot_max_order );
SHrotmatgen( SHrotmat, hHeadTrackData->Rmat, shd_rot_max_order );
+#endif
for ( i = 0; i < subframe_len; i++ )
{
@@ -338,7 +349,11 @@ void rotateFrame_shd(
/* move Rmat to Rmat_prev */
for ( i = 0; i < 3; i++ )
{
+#ifdef EXTERNAL_ORIENTATIONS
+ mvr2r( hCombinedOrientationData->Rmat[subframe_idx][i], hCombinedOrientationData->Rmat_prev[i], 3 );
+#else
mvr2r( hHeadTrackData->Rmat[i], hHeadTrackData->Rmat_prev[i], 3 );
+#endif
}
return;
@@ -352,12 +367,16 @@ void rotateFrame_shd(
*------------------------------------------------------------------------*/
void rotateFrame_sd(
+#ifdef EXTERNAL_ORIENTATIONS
+ COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, /* i : head and external orientation combined handle */
+#else
HEAD_TRACK_DATA_HANDLE hHeadTrackData, /* i : head track handle */
- float *output[], /* i/o: unrotated SD signal buffer in TD */
- const int16_t subframe_len, /* i : subframe length per channel */
- const IVAS_OUTPUT_SETUP hTransSetup, /* i : format for rotation */
- const EFAP_HANDLE hEFAPdata, /* i : EFAP structure */
- const int16_t subframe_idx /* i : subframe index */
+#endif
+ float *output[], /* i/o: unrotated SD signal buffer in TD */
+ const int16_t subframe_len, /* i : subframe length per channel */
+ const IVAS_OUTPUT_SETUP hTransSetup, /* i : format for rotation */
+ const EFAP_HANDLE hEFAPdata, /* i : EFAP structure */
+ const int16_t subframe_idx /* i : subframe index */
)
{
int16_t i, j;
@@ -383,8 +402,10 @@ void rotateFrame_sd(
cross_fade[i] = i * tmp;
}
+#ifndef EXTERNAL_ORIENTATIONS
/* Get next quaternion and calculate rotation matrix */
QuatToRotMat( hHeadTrackData->Quaternions[hHeadTrackData->num_quaternions++], hHeadTrackData->Rmat );
+#endif
for ( ch_in = 0; ch_in < nchan; ch_in++ )
{
@@ -407,7 +428,11 @@ void rotateFrame_sd(
ch_in_woLFE = ( ch_in >= index_lfe ) ? ch_in - 1 : ch_in;
/* gains for previous subframe rotation */
+#ifdef EXTERNAL_ORIENTATIONS
+ rotateAziEle( hTransSetup.ls_azimuth[ch_in_woLFE], hTransSetup.ls_elevation[ch_in_woLFE], &azimuth, &elevation, hCombinedOrientationData->Rmat_prev, hTransSetup.is_planar_setup );
+#else
rotateAziEle( hTransSetup.ls_azimuth[ch_in_woLFE], hTransSetup.ls_elevation[ch_in_woLFE], &azimuth, &elevation, hHeadTrackData->Rmat_prev, hTransSetup.is_planar_setup );
+#endif
if ( hEFAPdata != NULL && ( hTransSetup.ls_azimuth[ch_in_woLFE] != azimuth || hTransSetup.ls_elevation[ch_in_woLFE] != elevation ) )
{
efap_determine_gains( hEFAPdata, tmp_gains, azimuth, elevation, EFAP_MODE_EFAP );
@@ -428,7 +453,11 @@ void rotateFrame_sd(
/* gains for current subframe rotation */
+#ifdef EXTERNAL_ORIENTATIONS
+ rotateAziEle( hTransSetup.ls_azimuth[ch_in_woLFE], hTransSetup.ls_elevation[ch_in_woLFE], &azimuth, &elevation, hCombinedOrientationData->Rmat[subframe_idx], hTransSetup.is_planar_setup );
+#else
rotateAziEle( hTransSetup.ls_azimuth[ch_in_woLFE], hTransSetup.ls_elevation[ch_in_woLFE], &azimuth, &elevation, hHeadTrackData->Rmat, hTransSetup.is_planar_setup );
+#endif
if ( hEFAPdata != NULL && ( hTransSetup.ls_azimuth[ch_in_woLFE] != azimuth || hTransSetup.ls_elevation[ch_in_woLFE] != elevation ) )
{
efap_determine_gains( hEFAPdata, tmp_gains, azimuth, elevation, EFAP_MODE_EFAP );
@@ -465,7 +494,11 @@ void rotateFrame_sd(
/* move Rmat to Rmat_prev */
for ( i = 0; i < 3; i++ )
{
+#ifdef EXTERNAL_ORIENTATIONS
+ mvr2r( hCombinedOrientationData->Rmat[subframe_idx][i], hCombinedOrientationData->Rmat_prev[i], 3 );
+#else
mvr2r( hHeadTrackData->Rmat[i], hHeadTrackData->Rmat_prev[i], 3 );
+#endif
}
/* copy to output */
@@ -581,7 +614,11 @@ void rotateFrame_shd_cldfb(
*------------------------------------------------------------------------*/
void rotateFrame_sd_cldfb(
- HEAD_TRACK_DATA_HANDLE hHeadTrackData, /* i : head track handle */
+#ifdef EXTERNAL_ORIENTATIONS
+ float Rmat[3][3], /* i : real-space rotation matrix */
+#else
+ HEAD_TRACK_DATA_HANDLE hHeadTrackData, /* i : head track handle */
+#endif
float Cldfb_RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i/o: unrotated HOA3 signal buffer in cldfb domain real part */
float Cldfb_ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i/o: unrotated HOA3 signal buffer in cldfb domain imag part */
const IVAS_OUTPUT_SETUP_HANDLE hOutputSetup, /* i : output format setup number of channels */
@@ -593,7 +630,9 @@ void rotateFrame_sd_cldfb(
int16_t iBlock, iBand, m, n;
float gains[MAX_CICP_CHANNELS - 1][MAX_CICP_CHANNELS - 1];
int16_t azimuth, elevation;
+#ifndef EXTERNAL_ORIENTATIONS
float Rmat[3][3];
+#endif
float g1;
float realRot[MAX_CICP_CHANNELS - 1][MAX_PARAM_SPATIAL_SUBFRAMES * CLDFB_NO_CHANNELS_MAX];
float imagRot[MAX_CICP_CHANNELS - 1][MAX_PARAM_SPATIAL_SUBFRAMES * CLDFB_NO_CHANNELS_MAX];
@@ -615,8 +654,10 @@ void rotateFrame_sd_cldfb(
}
}
+#ifndef EXTERNAL_ORIENTATIONS
/* Get next quaternion and calculate rotation matrix */
QuatToRotMat( hHeadTrackData->Quaternions[hHeadTrackData->num_quaternions++], Rmat );
+#endif
/* rotation of Euler angles */
for ( n = 0; n < nInChannels; n++ )
@@ -686,6 +727,542 @@ void rotateFrame_sd_cldfb(
return;
}
+
+#ifdef EXTERNAL_ORIENTATIONS
+/*-----------------------------------------------------------------------*
+ * ivas_external_orientation_open()
+ *
+ * Allocate and initialize external orientation handle
+ *-----------------------------------------------------------------------*/
+
+ivas_error ivas_external_orientation_open(
+ EXTERNAL_ORIENTATION_HANDLE *hExtOrientationData /* o : external orientation handle */
+)
+{
+ int16_t i;
+ IVAS_QUATERNION identity;
+
+ identity.w = 1.0f;
+ identity.x = identity.y = identity.z = 0.0f;
+
+ /* Allocate handle */
+ if ( ( *hExtOrientationData = (EXTERNAL_ORIENTATION_HANDLE) malloc( sizeof( EXTERNAL_ORIENTATION_DATA ) ) ) == NULL )
+ {
+ return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for external orientation memory\n" ) );
+ }
+
+ /* Enable head rotation and disable external orientation as default */
+ for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
+ {
+ ( *hExtOrientationData )->enableHeadRotation[i] = 1;
+ ( *hExtOrientationData )->enableExternalOrientation[i] = 0;
+ ( *hExtOrientationData )->enableRotationInterpolation[i] = 0;
+ ( *hExtOrientationData )->numFramesToTargetOrientation[i] = 0;
+ ( *hExtOrientationData )->Quaternions[i] = identity;
+ }
+
+ return IVAS_ERR_OK;
+}
+
+
+/*-----------------------------------------------------------------------*
+ * ivas_external_orientation_close()
+ *
+ * Deallocate external orientation handle
+ *-----------------------------------------------------------------------*/
+
+void ivas_external_orientation_close(
+ EXTERNAL_ORIENTATION_HANDLE *hExtOrientationData /* i/o: external orientation handle */
+)
+{
+ if ( hExtOrientationData == NULL || *hExtOrientationData == NULL )
+ {
+ return;
+ }
+
+ free( ( *hExtOrientationData ) );
+ *hExtOrientationData = NULL;
+
+ return;
+}
+
+
+/*-----------------------------------------------------------------------*
+ * ivas_combined_orientation_open()
+ *
+ * Allocate and initialize combined orientation handle
+ *-----------------------------------------------------------------------*/
+
+ivas_error ivas_combined_orientation_open(
+ COMBINED_ORIENTATION_HANDLE *hCombinedOrientationData /* o : combined orientation handle */
+)
+{
+ int16_t i, j;
+ IVAS_QUATERNION identity;
+
+ identity.w = 1.0f;
+ identity.x = identity.y = identity.z = 0.0f;
+
+ /* Allocate handle */
+ if ( ( *hCombinedOrientationData = (COMBINED_ORIENTATION_HANDLE) malloc( sizeof( COMBINED_ORIENTATION_DATA ) ) ) == NULL )
+ {
+ return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for combined orientation memory\n" ) );
+ }
+
+ /* Initialization */
+ ( *hCombinedOrientationData )->interpolationCoefficient = 1.0f;
+ ( *hCombinedOrientationData )->interpolationIncrement = 1.0f;
+ ( *hCombinedOrientationData )->maximumFramesToTargetOrientation = 500;
+ ( *hCombinedOrientationData )->lrSwitchedNext = 0;
+ ( *hCombinedOrientationData )->lrSwitchedCurrent = 0;
+ ( *hCombinedOrientationData )->lrSwitchInterpVal = 0.0f;
+ ( *hCombinedOrientationData )->isInterpolationOngoing = FALSE;
+ ( *hCombinedOrientationData )->Quaternions_ext_interpolation_start = identity;
+ ( *hCombinedOrientationData )->Quaternions_ext_interpolation_target = identity;
+
+ /* Initialise orientations to identity */
+ for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
+ {
+ ( *hCombinedOrientationData )->enableCombinedOrientation[i] = 0;
+ ( *hCombinedOrientationData )->Quaternions[i] = identity;
+ ( *hCombinedOrientationData )->Quaternions_prev_headRot[i] = identity;
+ ( *hCombinedOrientationData )->Quaternions_prev_extOrientation[i] = identity;
+
+ for ( j = 0; j < 3; j++ )
+ {
+ set_zero( ( *hCombinedOrientationData )->Rmat[i][j], 3 );
+ ( *hCombinedOrientationData )->Rmat[i][j][j] = 1.0f;
+ }
+ }
+
+ for ( j = 0; j < 3; j++ )
+ {
+ set_zero( ( *hCombinedOrientationData )->Rmat_prev[j], 3 );
+ ( *hCombinedOrientationData )->Rmat_prev[j][j] = 1.0f;
+ }
+
+ set_zero( ( *hCombinedOrientationData )->chEneIIR[0], MASA_FREQUENCY_BANDS );
+ set_zero( ( *hCombinedOrientationData )->chEneIIR[1], MASA_FREQUENCY_BANDS );
+ set_zero( ( *hCombinedOrientationData )->procChEneIIR[0], MASA_FREQUENCY_BANDS );
+ set_zero( ( *hCombinedOrientationData )->procChEneIIR[1], MASA_FREQUENCY_BANDS );
+
+ return IVAS_ERR_OK;
+}
+
+
+/*-----------------------------------------------------------------------*
+ * ivas_combined_orientation_close()
+ *
+ * Deallocate combined orientation handle
+ *-----------------------------------------------------------------------*/
+
+void ivas_combined_orientation_close(
+ COMBINED_ORIENTATION_HANDLE *hCombinedOrientationData /* i/o: combined orientation handle */
+)
+{
+ if ( hCombinedOrientationData == NULL || *hCombinedOrientationData == NULL )
+ {
+ return;
+ }
+
+ free( ( *hCombinedOrientationData ) );
+ *hCombinedOrientationData = NULL;
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------------
+ * combine_external_and_head_orientations_dec()
+ *
+ *
+ *------------------------------------------------------------------------*/
+
+ivas_error combine_external_and_head_orientations_dec(
+ HEAD_TRACK_DATA_HANDLE hHeadTrackData, /* i : head track handle */
+ EXTERNAL_ORIENTATION_HANDLE hExtOrientationData, /* i : external orientation handle */
+ COMBINED_ORIENTATION_HANDLE hCombinedOrientationData /* i/o: combined orientation handle */
+)
+{
+ IVAS_QUATERNION *headRotQuaternions = NULL;
+ int16_t numHeadRotQuaternions = 0;
+
+ if ( hHeadTrackData != NULL )
+ {
+ numHeadRotQuaternions = hHeadTrackData->num_quaternions;
+ if ( hHeadTrackData->num_quaternions >= 0 )
+ {
+ headRotQuaternions = hHeadTrackData->Quaternions;
+ }
+ }
+
+ return combine_external_and_head_orientations( headRotQuaternions, numHeadRotQuaternions, hExtOrientationData, hCombinedOrientationData );
+}
+
+
+/*-------------------------------------------------------------------------
+ * combine_external_and_head_orientations_rend()
+ *
+ *
+ *------------------------------------------------------------------------*/
+
+ivas_error combine_external_and_head_orientations_rend(
+ IVAS_REND_HeadRotData *hHeadTrackData, /* i : head track handle */
+ EXTERNAL_ORIENTATION_HANDLE hExtOrientationData, /* i : external orientation handle */
+ COMBINED_ORIENTATION_HANDLE hCombinedOrientationData /* i/o: combined orientation handle */
+)
+{
+ IVAS_QUATERNION *headRotQuaternions = NULL;
+ int16_t numHeadRotQuaternions = 0;
+ int16_t i;
+
+ if ( hHeadTrackData != NULL )
+ {
+ if ( hHeadTrackData->headRotEnabled )
+ {
+ headRotQuaternions = hHeadTrackData->headPositions;
+ }
+ }
+ else if ( hExtOrientationData != NULL )
+ {
+ /* Head rotation data not available, use the freezed value or disable */
+ for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
+ {
+ if ( hExtOrientationData->enableHeadRotation[i] != 2 )
+ {
+ hExtOrientationData->enableHeadRotation[i] = 0;
+ }
+ }
+ }
+
+ return combine_external_and_head_orientations( headRotQuaternions, numHeadRotQuaternions, hExtOrientationData, hCombinedOrientationData );
+}
+
+
+/*-------------------------------------------------------------------------
+ * combine_external_and_head_orientations()
+ *
+ * Combine the external orientations and the head orientation.
+ * NOTE that the external orientations are inversed.
+ *------------------------------------------------------------------------*/
+
+ivas_error combine_external_and_head_orientations(
+ IVAS_QUATERNION *headRotQuaternions, /* i : quaternions for head rotation */
+ int16_t numHeadRotQuaternions, /* i : number of head rotation quaternions */
+ EXTERNAL_ORIENTATION_HANDLE hExtOrientationData, /* i : external orientation handle */
+ COMBINED_ORIENTATION_HANDLE hCombinedOrientationData /* i/o: combined orientation handle */
+)
+{
+ int16_t i, j;
+ IVAS_QUATERNION identity;
+
+ identity.w = 1.0f;
+ identity.x = identity.y = identity.z = 0.0f;
+
+ /* Form combined orientations or return if no data available */
+ if ( hCombinedOrientationData == NULL )
+ {
+ if ( headRotQuaternions != NULL || hExtOrientationData != NULL )
+ {
+ return IVAS_ERR_UNEXPECTED_NULL_POINTER;
+ }
+ else
+ {
+ return IVAS_ERR_OK;
+ }
+ }
+ else if ( headRotQuaternions == NULL && hExtOrientationData == NULL )
+ {
+ /* Reset the combined orientations and rotations */
+ hCombinedOrientationData->isInterpolationOngoing = FALSE;
+ hCombinedOrientationData->interpolationCoefficient = 1.0f;
+ hCombinedOrientationData->interpolationIncrement = 1.0f;
+ hCombinedOrientationData->Quaternions_ext_interpolation_start = identity;
+ hCombinedOrientationData->Quaternions_ext_interpolation_target = identity;
+ for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
+ {
+ hCombinedOrientationData->enableCombinedOrientation[i] = 0;
+ hCombinedOrientationData->Quaternions[i] = identity;
+
+ for ( j = 0; j < 3; j++ )
+ {
+ set_zero( hCombinedOrientationData->Rmat[i][j], 3 );
+ hCombinedOrientationData->Rmat[i][j][j] = 1.0f;
+ }
+ }
+ }
+ else if ( hExtOrientationData == NULL && headRotQuaternions != NULL )
+ {
+ /* Head rotation only */
+ if ( numHeadRotQuaternions >= 0 )
+ {
+ for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
+ {
+ hCombinedOrientationData->Quaternions[i] = headRotQuaternions[i];
+ }
+ }
+ }
+
+ if ( hExtOrientationData != NULL )
+ {
+ /* External orientations */
+ for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
+ {
+ if ( hExtOrientationData->enableRotationInterpolation[i] == 1 && hExtOrientationData->enableExternalOrientation[i] > 0 )
+ {
+ if ( hCombinedOrientationData->isInterpolationOngoing == TRUE && hCombinedOrientationData->interpolationCoefficient <= 1.0f && are_orientations_same( &hCombinedOrientationData->Quaternions_ext_interpolation_target, &hExtOrientationData->Quaternions[i] ) == true )
+ {
+ /* Continue interpolation */
+ QuaternionSlerp( hCombinedOrientationData->Quaternions_ext_interpolation_start, hCombinedOrientationData->Quaternions_ext_interpolation_target, hCombinedOrientationData->interpolationCoefficient, &hCombinedOrientationData->Quaternions[i] );
+ hCombinedOrientationData->interpolationCoefficient += hCombinedOrientationData->interpolationIncrement;
+ }
+ else
+ {
+ /* Stop interpolation or check for new interpolation */
+ hCombinedOrientationData->isInterpolationOngoing = FALSE;
+ hCombinedOrientationData->interpolationCoefficient = 1.0f;
+ hCombinedOrientationData->interpolationIncrement = 1.0f;
+ external_target_interpolation( hExtOrientationData, hCombinedOrientationData, i );
+ }
+ }
+ else
+ {
+ /* Interpolation disabled, use the current orientation values */
+
+ /* Use the most recent external orientation */
+ if ( hExtOrientationData->enableExternalOrientation[i] == 1 )
+ {
+ hCombinedOrientationData->Quaternions[i] = hExtOrientationData->Quaternions[i];
+ }
+ /* Use the freezed external orientation */
+ else if ( hExtOrientationData->enableExternalOrientation[i] == 2 )
+ {
+ hCombinedOrientationData->Quaternions[i] = hCombinedOrientationData->Quaternions_prev_extOrientation[i];
+ }
+ }
+ }
+ }
+
+ if ( hExtOrientationData != NULL && headRotQuaternions != NULL )
+ {
+ /* Combine head and external orientations */
+ for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
+ {
+ /* Use the most recent head rotation */
+ if ( hExtOrientationData->enableHeadRotation[i] == 1 && numHeadRotQuaternions >= 0 )
+ {
+ if ( hExtOrientationData->enableExternalOrientation[i] > 0 )
+ {
+ QuaternionProduct( hCombinedOrientationData->Quaternions[i], headRotQuaternions[i], &hCombinedOrientationData->Quaternions[i] );
+ }
+ else
+ {
+ hCombinedOrientationData->Quaternions[i] = headRotQuaternions[i];
+ }
+ }
+ /* Use the freezed head rotation */
+ else if ( hExtOrientationData->enableHeadRotation[i] == 2 && numHeadRotQuaternions >= 0 )
+ {
+ if ( hExtOrientationData->enableExternalOrientation[i] > 0 )
+ {
+ QuaternionProduct( hCombinedOrientationData->Quaternions[i], hCombinedOrientationData->Quaternions_prev_headRot[i], &hCombinedOrientationData->Quaternions[i] );
+ }
+ else
+ {
+ hCombinedOrientationData->Quaternions[i] = hCombinedOrientationData->Quaternions_prev_headRot[i];
+ }
+ }
+
+ /* Reset the combined orientations to identity */
+ if ( hExtOrientationData->enableHeadRotation[i] == 0 && hExtOrientationData->enableExternalOrientation[i] == 0 )
+ {
+ hCombinedOrientationData->Quaternions[i] = identity;
+ }
+ }
+ }
+
+ if ( headRotQuaternions != NULL || hExtOrientationData != NULL )
+ {
+ /* Calculate the combined rotation matrix */
+ for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
+ {
+ QuatToRotMat( hCombinedOrientationData->Quaternions[i], hCombinedOrientationData->Rmat[i] );
+ }
+ }
+
+ /* Save the current orientations */
+ if ( hExtOrientationData != NULL )
+ {
+ for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
+ {
+ if ( hExtOrientationData->enableExternalOrientation[i] > 0 )
+ {
+ hCombinedOrientationData->Quaternions_prev_extOrientation[i] = hCombinedOrientationData->Quaternions[i];
+ }
+ else
+ {
+ hCombinedOrientationData->Quaternions_prev_extOrientation[i] = identity;
+ }
+ }
+ }
+ if ( headRotQuaternions != NULL )
+ {
+ for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
+ {
+ if ( hExtOrientationData != NULL )
+ {
+ if ( hExtOrientationData->enableHeadRotation[i] > 0 && numHeadRotQuaternions >= 0 )
+ {
+ hCombinedOrientationData->Quaternions_prev_headRot[i] = headRotQuaternions[i];
+ }
+ else
+ {
+ hCombinedOrientationData->Quaternions_prev_headRot[i] = identity;
+ }
+ }
+ else
+ {
+ if ( numHeadRotQuaternions >= 0 )
+ {
+ hCombinedOrientationData->Quaternions_prev_headRot[i] = headRotQuaternions[i];
+ }
+ else
+ {
+ hCombinedOrientationData->Quaternions_prev_headRot[i] = identity;
+ }
+ }
+ }
+ }
+
+ /* Check if combined orientation is enabled */
+ if ( headRotQuaternions != NULL && hExtOrientationData == NULL )
+ {
+ for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
+ {
+ if ( numHeadRotQuaternions >= 0 )
+ {
+ hCombinedOrientationData->enableCombinedOrientation[i] = 1;
+ }
+ else
+ {
+ hCombinedOrientationData->enableCombinedOrientation[i] = 0;
+ }
+ }
+ }
+ else if ( headRotQuaternions == NULL && hExtOrientationData != NULL )
+ {
+ for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
+ {
+ if ( hExtOrientationData->enableExternalOrientation[i] > 0 )
+ {
+ hCombinedOrientationData->enableCombinedOrientation[i] = 1;
+ }
+ else
+ {
+ hCombinedOrientationData->enableCombinedOrientation[i] = 0;
+ }
+ }
+ }
+ else if ( headRotQuaternions != NULL && hExtOrientationData != NULL )
+ {
+ for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
+ {
+ if ( hExtOrientationData->enableExternalOrientation[i] > 0 || ( hExtOrientationData->enableHeadRotation[i] > 0 && numHeadRotQuaternions >= 0 ) )
+ {
+ hCombinedOrientationData->enableCombinedOrientation[i] = 1;
+ }
+ else
+ {
+ hCombinedOrientationData->enableCombinedOrientation[i] = 0;
+ }
+ }
+ }
+ else
+ {
+ for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
+ {
+ hCombinedOrientationData->enableCombinedOrientation[i] = 0;
+ }
+ }
+
+ return IVAS_ERR_OK;
+}
+
+
+/*-------------------------------------------------------------------------
+ * external_target_interpolation()
+ *
+ *
+ *------------------------------------------------------------------------*/
+
+void external_target_interpolation(
+ EXTERNAL_ORIENTATION_HANDLE hExtOrientationData, /* i : external orientation handle */
+ COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, /* i/o: combined orientation handle */
+ const int16_t i )
+{
+ /* Sanity check for number of frames */
+ hExtOrientationData->numFramesToTargetOrientation[i] = min( hExtOrientationData->numFramesToTargetOrientation[i], hCombinedOrientationData->maximumFramesToTargetOrientation );
+ hExtOrientationData->numFramesToTargetOrientation[i] = max( hExtOrientationData->numFramesToTargetOrientation[i], 0 );
+
+ /* Interpolate from the current orientation to the target orientation */
+ if ( hExtOrientationData->numFramesToTargetOrientation[i] > 0 )
+ {
+ if ( are_orientations_same( &hCombinedOrientationData->Quaternions_ext_interpolation_target, &hExtOrientationData->Quaternions[i] ) == false )
+ {
+ /* Target orientation is different from the previous target, update the values */
+
+ /* Set the received orientation as the target */
+ hCombinedOrientationData->Quaternions_ext_interpolation_target = hExtOrientationData->Quaternions[i];
+
+ /* Use the most recent external orientation as the starting orientation */
+ hCombinedOrientationData->Quaternions_ext_interpolation_start = hCombinedOrientationData->Quaternions_prev_extOrientation[i];
+
+ /* Calculate the interpolation increment and coefficient */
+ hCombinedOrientationData->interpolationIncrement = 1.0f / ( (float) hExtOrientationData->numFramesToTargetOrientation[i] * (float) MAX_PARAM_SPATIAL_SUBFRAMES );
+ hCombinedOrientationData->interpolationCoefficient = hCombinedOrientationData->interpolationIncrement;
+ }
+
+ /* Interpolate */
+ hCombinedOrientationData->isInterpolationOngoing = TRUE;
+ QuaternionSlerp( hCombinedOrientationData->Quaternions_ext_interpolation_start, hCombinedOrientationData->Quaternions_ext_interpolation_target, hCombinedOrientationData->interpolationCoefficient, &hCombinedOrientationData->Quaternions[i] );
+ hCombinedOrientationData->interpolationCoefficient += hCombinedOrientationData->interpolationIncrement;
+ }
+ else
+ {
+ /* Use the target orientation immediately */
+ hCombinedOrientationData->isInterpolationOngoing = FALSE;
+ hCombinedOrientationData->interpolationCoefficient = 1.0f;
+ hCombinedOrientationData->interpolationIncrement = 1.0f;
+ hCombinedOrientationData->Quaternions[i] = hExtOrientationData->Quaternions[i];
+ }
+}
+
+
+/*-------------------------------------------------------------------------
+ * are_orientations_same()
+ *
+ *
+ *------------------------------------------------------------------------*/
+
+bool are_orientations_same(
+ const IVAS_QUATERNION *orientation1,
+ const IVAS_QUATERNION *orientation2 )
+{
+ bool orientationsAreSame = true;
+ float error_margin = 0.05f;
+ if ( fabsf( orientation1->w - orientation2->w ) > error_margin ||
+ fabsf( orientation1->x - orientation2->x ) > error_margin ||
+ fabsf( orientation1->y - orientation2->y ) > error_margin ||
+ fabsf( orientation1->z - orientation2->z ) > error_margin )
+ {
+ orientationsAreSame = false;
+ }
+
+ return orientationsAreSame;
+}
+
+#endif // EXTERNAL_ORIENTATIONS
+
/*-----------------------------------------------------------------------*
* Local Function definitions
*-----------------------------------------------------------------------*/
diff --git a/lib_rend/ivas_stat_rend.h b/lib_rend/ivas_stat_rend.h
index b90b7b55077d08ba60f68c495c4e0b1fdc02d823..2d6419ed8c4957c41d07cb2947cd7881de758e9b 100644
--- a/lib_rend/ivas_stat_rend.h
+++ b/lib_rend/ivas_stat_rend.h
@@ -274,6 +274,48 @@ typedef struct ivas_binaural_head_track_struct
} HEAD_TRACK_DATA, *HEAD_TRACK_DATA_HANDLE;
+#ifdef EXTERNAL_ORIENTATIONS
+/*----------------------------------------------------------------------------------*
+ * External orientation data structure
+ *----------------------------------------------------------------------------------*/
+
+typedef struct ivas_external_orientation_struct
+{
+ int8_t enableHeadRotation[MAX_PARAM_SPATIAL_SUBFRAMES]; /* 0 - disable, 1 - enable, 2 - freeze to previous rotation */
+ int8_t enableExternalOrientation[MAX_PARAM_SPATIAL_SUBFRAMES]; /* 0 - disable, 1 - enable, 2 - freeze to previous orientation */
+ int8_t enableRotationInterpolation[MAX_PARAM_SPATIAL_SUBFRAMES]; /* 0 - disable, 1 - enable */
+ int16_t numFramesToTargetOrientation[MAX_PARAM_SPATIAL_SUBFRAMES]; /* Number of frames until target orientation is reached */
+ IVAS_QUATERNION Quaternions[MAX_PARAM_SPATIAL_SUBFRAMES]; /* External orientation in quaternions */
+
+} EXTERNAL_ORIENTATION_DATA, *EXTERNAL_ORIENTATION_HANDLE;
+
+/*----------------------------------------------------------------------------------*
+ * Combined orientation data structure for the external orienations and head orientation
+ *----------------------------------------------------------------------------------*/
+
+typedef struct ivas_combined_orientation_struct
+{
+ int16_t enableCombinedOrientation[MAX_PARAM_SPATIAL_SUBFRAMES];
+ float interpolationCoefficient;
+ float interpolationIncrement;
+ int16_t maximumFramesToTargetOrientation;
+ uint8_t lrSwitchedNext;
+ uint8_t lrSwitchedCurrent;
+ float lrSwitchInterpVal;
+ bool isInterpolationOngoing;
+ IVAS_QUATERNION Quaternions[MAX_PARAM_SPATIAL_SUBFRAMES];
+ IVAS_QUATERNION Quaternions_prev_headRot[MAX_PARAM_SPATIAL_SUBFRAMES];
+ IVAS_QUATERNION Quaternions_prev_extOrientation[MAX_PARAM_SPATIAL_SUBFRAMES];
+ IVAS_QUATERNION Quaternions_ext_interpolation_start;
+ IVAS_QUATERNION Quaternions_ext_interpolation_target;
+ float Rmat[MAX_PARAM_SPATIAL_SUBFRAMES][3][3];
+ float Rmat_prev[3][3];
+ float chEneIIR[2][MASA_FREQUENCY_BANDS]; /* independent of the format. MASA bands are suitable for the task and readily available in ROM. */
+ float procChEneIIR[2][MASA_FREQUENCY_BANDS];
+
+} COMBINED_ORIENTATION_DATA, *COMBINED_ORIENTATION_HANDLE;
+#endif
+
/*----------------------------------------------------------------------------------*
* Reverberator structure
*----------------------------------------------------------------------------------*/
diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c
index b4a0950c5fbce72577bab6f78ef74c5ddf6a181e..f4a51d44c9e8b3c4f93ceb9975dd767453d4f335 100644
--- a/lib_rend/lib_rend.c
+++ b/lib_rend/lib_rend.c
@@ -95,6 +95,9 @@ typedef struct
* multiple rendering configurations unless one global one can be used. If this is not relevant,
* feel free to remove this TODO.
*/
+#ifdef EXTERNAL_ORIENTATIONS
+ const COMBINED_ORIENTATION_HANDLE *pCombinedOrientationData;
+#endif
} rendering_context;
/* Common base for input structs */
@@ -193,6 +196,11 @@ struct IVAS_REND
IVAS_REND_HeadRotData headRotData;
+#ifdef EXTERNAL_ORIENTATIONS
+ EXTERNAL_ORIENTATION_HANDLE hExternalOrientationData;
+ COMBINED_ORIENTATION_HANDLE hCombinedOrientationData;
+#endif
+
int8_t rendererConfigEnabled;
RENDER_CONFIG_DATA *hRendererConfig; /* Renderer config pointer */
};
@@ -953,6 +961,7 @@ static void closeHeadRotation(
return;
}
+
static void initRotMatrix(
rotation_matrix rot_mat )
{
@@ -1032,6 +1041,9 @@ static rendering_context getRendCtx(
ctx.pCustomLsOut = &hIvasRend->customLsOut;
ctx.pEfapOutWrapper = &hIvasRend->efapOutWrapper;
ctx.pHeadRotData = &hIvasRend->headRotData;
+#ifdef EXTERNAL_ORIENTATIONS
+ ctx.pCombinedOrientationData = &hIvasRend->hCombinedOrientationData;
+#endif
return ctx;
}
@@ -2510,10 +2522,28 @@ static DecoderDummy *initDecoderDummy(
decDummy->hHeadTrackData->lrSwitchedNext = 0;
decDummy->hHeadTrackData->OrientationTracker = (ivas_orient_trk_state_t *) malloc( sizeof( ivas_orient_trk_state_t ) );
ivas_orient_trk_Init( decDummy->hHeadTrackData->OrientationTracker );
+
+#ifdef EXTERNAL_ORIENTATIONS
+ /* External orientations */
+ if ( ( error = ivas_external_orientation_open( &( decDummy->hExtOrientationData ) ) ) != IVAS_ERR_OK )
+ {
+ assert( error == IVAS_ERR_OK );
+ }
+
+ /* Combined orientations */
+ if ( ( error = ivas_combined_orientation_open( &( decDummy->hCombinedOrientationData ) ) ) != IVAS_ERR_OK )
+ {
+ assert( error == IVAS_ERR_OK );
+ }
+#endif
}
else
{
decDummy->hHeadTrackData = NULL;
+#ifdef EXTERNAL_ORIENTATIONS
+ decDummy->hExtOrientationData = NULL;
+ decDummy->hCombinedOrientationData = NULL;
+#endif
}
if ( enableRenderConfig )
@@ -2599,6 +2629,17 @@ static void freeDecoderDummy(
}
free( pDecDummy->hHeadTrackData );
}
+#ifdef EXTERNAL_ORIENTATIONS
+ if ( pDecDummy->hExtOrientationData != NULL )
+ {
+ free( pDecDummy->hExtOrientationData );
+ }
+ if ( pDecDummy->hCombinedOrientationData != NULL )
+ {
+ free( pDecDummy->hCombinedOrientationData );
+ }
+#endif
+
ivas_render_config_close( &pDecDummy->hRenderConfig );
/* CLDFB handles */
@@ -2721,6 +2762,20 @@ ivas_error IVAS_REND_Open(
return error;
}
+#ifdef EXTERNAL_ORIENTATIONS
+ /* Initialize external orientation data */
+ if ( ( error = ivas_external_orientation_open( &( hIvasRend->hExternalOrientationData ) ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+
+ /* Initilize combined orientation data */
+ if ( ( error = ivas_combined_orientation_open( &( hIvasRend->hCombinedOrientationData ) ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+#endif
+
/* Initialize EFAP */
if ( ( error = initEfap( &hIvasRend->efapOutWrapper, outConfig, &hIvasRend->customLsOut ) ) != IVAS_ERR_OK )
{
@@ -4002,6 +4057,104 @@ ivas_error IVAS_REND_SetReferenceVector(
}
+#ifdef EXTERNAL_ORIENTATIONS
+/*---------------------------------------------------------------------*
+ * IVAS_REND_SetExternalOrientation()
+ *
+ *
+ *---------------------------------------------------------------------*/
+
+ivas_error IVAS_REND_SetExternalOrientation(
+ IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */
+ IVAS_QUATERNION *orientation, /* i : external orientation data */
+ int8_t *enableHeadRotation, /* i : flag to enable head rotation for this frame */
+ int8_t *enableExternalOrientation, /* i : flag to enable external orientation for this frame */
+ int8_t *enableRotationInterpolation, /* i : flag to interpolate rotations from current and previous frames */
+ int16_t *numFramesToTargetOrientation /* i : number of frames until target orientation is reached */
+)
+{
+ int16_t i;
+
+ /* Validate function arguments */
+ if ( hIvasRend == NULL || hIvasRend->hExternalOrientationData == NULL )
+ {
+ return IVAS_ERR_UNEXPECTED_NULL_POINTER;
+ }
+
+ if ( orientation == NULL )
+ {
+ for ( i = 0; i < RENDERER_HEAD_POSITIONS_PER_FRAME; ++i )
+ {
+ hIvasRend->hExternalOrientationData->enableExternalOrientation[i] = 0;
+ }
+ }
+ else
+ {
+ for ( i = 0; i < RENDERER_HEAD_POSITIONS_PER_FRAME; ++i )
+ {
+ QuaternionInverse( orientation[i], &hIvasRend->hExternalOrientationData->Quaternions[i] );
+
+ hIvasRend->hExternalOrientationData->enableHeadRotation[i] = enableHeadRotation[i];
+ hIvasRend->hExternalOrientationData->enableExternalOrientation[i] = enableExternalOrientation[i];
+ hIvasRend->hExternalOrientationData->enableRotationInterpolation[i] = enableRotationInterpolation[i];
+ hIvasRend->hExternalOrientationData->numFramesToTargetOrientation[i] = numFramesToTargetOrientation[i];
+ }
+ }
+
+ return IVAS_ERR_OK;
+}
+
+
+/*---------------------------------------------------------------------*
+ * IVAS_REND_CombineHeadAndExternalOrientation()
+ *
+ *
+ *---------------------------------------------------------------------*/
+
+ivas_error IVAS_REND_CombineHeadAndExternalOrientation(
+ IVAS_REND_HANDLE hIvasRend /* i/o: Renderer handle */
+)
+{
+ if ( hIvasRend == NULL )
+ {
+ return IVAS_ERR_UNEXPECTED_NULL_POINTER;
+ }
+
+ return combine_external_and_head_orientations_rend( &hIvasRend->headRotData, hIvasRend->hExternalOrientationData, hIvasRend->hCombinedOrientationData );
+}
+
+
+/*---------------------------------------------------------------------*
+ * IVAS_REND_GetCombinedOrientation()
+ *
+ *
+ *---------------------------------------------------------------------*/
+
+ivas_error IVAS_REND_GetCombinedOrientation(
+ IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */
+ IVAS_QUATERNION *pOrientation /* i/o: Quaternion pointer processed orientation */
+)
+{
+ int16_t i;
+
+ if ( hIvasRend == NULL || pOrientation == NULL )
+ {
+ return IVAS_ERR_UNEXPECTED_NULL_POINTER;
+ }
+
+ if ( hIvasRend->hCombinedOrientationData != NULL )
+ {
+ for ( i = 0; i < RENDERER_HEAD_POSITIONS_PER_FRAME; ++i )
+ {
+ pOrientation[i] = hIvasRend->hCombinedOrientationData->Quaternions[i];
+ }
+ }
+
+ return IVAS_ERR_OK;
+}
+#endif
+
+
/*-------------------------------------------------------------------*
* Local functions
*-------------------------------------------------------------------*/
@@ -4097,12 +4250,18 @@ static ivas_error rotateFrameMc(
IVAS_REND_AudioConfig inConfig, /* i : Input Audio config */
LSSETUP_CUSTOM_STRUCT inCustomLs, /* i : Input Custom LS setup */
const IVAS_REND_HeadRotData *headRotData, /* i : Head rotation data */
- rotation_gains gains_prev, /* i/o: Previous frame rotation gains */
- const EFAP_HANDLE hEFAPdata, /* i : EFAP structure */
- IVAS_REND_AudioBuffer outAudio /* o : Output Audio buffer */
+#ifdef EXTERNAL_ORIENTATIONS
+ const COMBINED_ORIENTATION_HANDLE *hCombinedOrientationData, /* i : Combined head and external orientations */
+#endif
+ rotation_gains gains_prev, /* i/o: Previous frame rotation gains */
+ const EFAP_HANDLE hEFAPdata, /* i : EFAP structure */
+ IVAS_REND_AudioBuffer outAudio /* o : Output Audio buffer */
)
{
int16_t i;
+#ifdef EXTERNAL_ORIENTATIONS
+ int16_t j;
+#endif
int16_t subframe_idx, subframe_len;
int16_t azimuth, elevation;
int16_t is_planar_setup, lfe_idx;
@@ -4146,8 +4305,27 @@ static ivas_error rotateFrameMc(
subframe_len = inAudio.config.numSamplesPerChannel / RENDERER_HEAD_POSITIONS_PER_FRAME;
for ( subframe_idx = 0; subframe_idx < RENDERER_HEAD_POSITIONS_PER_FRAME; subframe_idx++ )
{
+#ifdef EXTERNAL_ORIENTATIONS
+ for ( i = 0; i < 3; i++ )
+ {
+ if ( hCombinedOrientationData != NULL )
+ {
+ for ( j = 0; j < 3; j++ )
+ {
+ Rmat[i][j] = ( *hCombinedOrientationData )->Rmat[subframe_idx][i][j];
+ }
+ }
+ else
+ {
+ /* Set to identity */
+ set_zero( Rmat[i], 3 );
+ Rmat[i][i] = 1.0f;
+ }
+ }
+#else
/* Get next quaternion and calculate rotation matrix */
QuatToRotMat( headRotData->headPositions[subframe_idx], Rmat );
+#endif
for ( ch_in = 0; ch_in < nchan; ch_in++ )
{
@@ -4217,8 +4395,11 @@ static ivas_error rotateFrameSba(
IVAS_REND_AudioBuffer inAudio, /* i : Input Audio buffer */
IVAS_REND_AudioConfig inConfig, /* i : Input Audio config */
const IVAS_REND_HeadRotData *headRotData, /* i : Head rotation data */
- rotation_gains gains_prev, /* i/o: Previous frame rotation gains */
- IVAS_REND_AudioBuffer outAudio /* o : Output Audio buffer */
+#ifdef EXTERNAL_ORIENTATIONS
+ const COMBINED_ORIENTATION_HANDLE *hCombinedOrientationData, /* i : Combined head and external orientations */
+#endif
+ rotation_gains gains_prev, /* i/o: Previous frame rotation gains */
+ IVAS_REND_AudioBuffer outAudio /* o : Output Audio buffer */
)
{
int16_t i, l, n, m;
@@ -4248,8 +4429,27 @@ static ivas_error rotateFrameSba(
set_zero( gains[i], HEADROT_SHMAT_DIM );
}
+#ifdef EXTERNAL_ORIENTATIONS
+ for ( i = 0; i < 3; i++ )
+ {
+ if ( hCombinedOrientationData != NULL )
+ {
+ for ( l = 0; l < 3; l++ )
+ {
+ Rmat[i][l] = ( *hCombinedOrientationData )->Rmat[subframe_idx][i][l];
+ }
+ }
+ else
+ {
+ /* Set to identity */
+ set_zero( Rmat[i], 3 );
+ Rmat[i][i] = 1.0f;
+ }
+ }
+#else
/* Get next quaternion and calculate rotation matrix */
QuatToRotMat( headRotData->headPositions[subframe_idx], Rmat );
+#endif
/* calculate ambisonics rotation matrices for the previous and current frames */
SHrotmatgen( gains, Rmat, shd_rot_max_order );
@@ -4330,6 +4530,9 @@ static ivas_error renderIsmToBinaural(
ismInput->base.inConfig,
NULL,
ismInput->base.ctx.pHeadRotData,
+#ifdef EXTERNAL_ORIENTATIONS
+ ismInput->base.ctx.pCombinedOrientationData,
+#endif
&ismInput->currentPos,
ismInput->hReverb,
outAudio.config.numSamplesPerChannel,
@@ -4355,13 +4558,19 @@ static ivas_error renderIsmToBinauralRoom(
int16_t tmp;
rotation_matrix Rmat;
float tmpRendBuffer[MAX_OUTPUT_CHANNELS][L_FRAME48k];
- IVAS_QUATERNION quat;
ivas_error error;
pan_vector currentPanGains;
pan_vector previousPanGains;
IVAS_REND_AudioBuffer tmpMcBuffer;
IVAS_REND_AudioObjectPosition rotatedPos;
+#ifdef EXTERNAL_ORIENTATIONS
+ const COMBINED_ORIENTATION_HANDLE *hCombinedOrientationData;
+ int8_t combinedOrientationEnabled;
+ int16_t j;
+#else
+ IVAS_QUATERNION quat;
const IVAS_REND_HeadRotData *headRotData;
+#endif
float *p_tmpRendBuffer[MAX_OUTPUT_CHANNELS];
for ( i = 0; i < MAX_OUTPUT_CHANNELS; i++ )
@@ -4371,10 +4580,32 @@ static ivas_error renderIsmToBinauralRoom(
push_wmops( "renderIsmToBinauralRoom" );
- headRotData = ismInput->base.ctx.pHeadRotData;
rotatedPos = defaultObjectPosition();
- if ( ismInput->hReverb != NULL && ismInput->hReverb->pConfig.roomAcoustics.use_brir == 0 && ismInput->hReverb->pConfig.roomAcoustics.late_reverb_on == 1 && headRotData->headRotEnabled )
+#ifdef EXTERNAL_ORIENTATIONS
+ hCombinedOrientationData = ismInput->base.ctx.pCombinedOrientationData;
+ combinedOrientationEnabled = 0;
+ if ( hCombinedOrientationData != NULL )
+ {
+ for ( subframe_idx = 0; subframe_idx < MAX_PARAM_SPATIAL_SUBFRAMES; subframe_idx++ )
+ {
+ if ( ( *hCombinedOrientationData )->enableCombinedOrientation[subframe_idx] != 0 )
+ {
+ combinedOrientationEnabled = 1;
+ break;
+ }
+ }
+ }
+#else
+ headRotData = ismInput->base.ctx.pHeadRotData;
+#endif
+
+ if ( ismInput->hReverb != NULL && ismInput->hReverb->pConfig.roomAcoustics.use_brir == 0 && ismInput->hReverb->pConfig.roomAcoustics.late_reverb_on == 1 &&
+#ifdef EXTERNAL_ORIENTATIONS
+ combinedOrientationEnabled )
+#else
+ headRotData->headRotEnabled )
+#endif
{
copyBufferTo2dArray( ismInput->base.inputBuffer, tmpRendBuffer );
@@ -4382,6 +4613,9 @@ static ivas_error renderIsmToBinauralRoom(
ismInput->base.inConfig,
NULL,
ismInput->base.ctx.pHeadRotData,
+#ifdef EXTERNAL_ORIENTATIONS
+ ismInput->base.ctx.pCombinedOrientationData,
+#endif
&ismInput->currentPos,
ismInput->hReverb,
outAudio.config.numSamplesPerChannel,
@@ -4393,19 +4627,41 @@ static ivas_error renderIsmToBinauralRoom(
}
else
{
-
+#ifdef EXTERNAL_ORIENTATIONS
+ if ( combinedOrientationEnabled )
+#else
if ( headRotData->headRotEnabled )
+#endif
{
subframe_len = ismInput->base.inputBuffer.config.numSamplesPerChannel / RENDERER_HEAD_POSITIONS_PER_FRAME;
// for ( subframe_idx = 0; subframe_idx < RENDERER_HEAD_POSITIONS_PER_FRAME; subframe_idx++ )
for ( subframe_idx = 0; subframe_idx < 1; subframe_idx++ )
{
+#ifdef EXTERNAL_ORIENTATIONS
+ for ( i = 0; i < 3; i++ )
+ {
+ if ( hCombinedOrientationData != NULL && ( *hCombinedOrientationData )->enableCombinedOrientation[subframe_idx] )
+ {
+ for ( j = 0; j < 3; j++ )
+ {
+ Rmat[i][j] = ( *hCombinedOrientationData )->Rmat[subframe_idx][i][j];
+ }
+ }
+ else
+ {
+ /* Set to identity */
+ set_zero( Rmat[i], 3 );
+ Rmat[i][i] = 1.0f;
+ }
+ }
+#else
quat.w = headRotData->headPositions[subframe_idx].w;
quat.x = headRotData->headPositions[subframe_idx].x;
quat.y = headRotData->headPositions[subframe_idx].y;
quat.z = headRotData->headPositions[subframe_idx].z;
QuatToRotMat( quat, Rmat );
+#endif
}
(void) subframe_len; // avoid warning
}
@@ -4414,7 +4670,11 @@ static ivas_error renderIsmToBinauralRoom(
/* Possible optimization: less processing needed if position didn't change
* needs a lot of cleanup, we could also add rot_gains_prev to ismInput and use that */
/* previous position gains */
+#ifdef EXTERNAL_ORIENTATIONS
+ if ( combinedOrientationEnabled )
+#else
if ( headRotData->headRotEnabled )
+#endif
{
rotateAziEle( ismInput->previousPos.azimuth, ismInput->previousPos.elevation, &azi_rot, &ele_rot, ismInput->rot_mat_prev, 0 );
rotatedPos.azimuth = (float) azi_rot;
@@ -4422,15 +4682,24 @@ static ivas_error renderIsmToBinauralRoom(
}
if ( ( error = getEfapGains( *ismInput->base.ctx.pEfapOutWrapper,
+#ifdef EXTERNAL_ORIENTATIONS
+ ( combinedOrientationEnabled ) ? rotatedPos.azimuth : ismInput->previousPos.azimuth,
+ ( combinedOrientationEnabled ) ? rotatedPos.elevation : ismInput->previousPos.elevation,
+#else
( headRotData->headRotEnabled ) ? rotatedPos.azimuth : ismInput->previousPos.azimuth,
( headRotData->headRotEnabled ) ? rotatedPos.elevation : ismInput->previousPos.elevation,
+#endif
previousPanGains ) ) != IVAS_ERR_OK )
{
return error;
}
/* current position gains */
+#ifdef EXTERNAL_ORIENTATIONS
+ if ( combinedOrientationEnabled )
+#else
if ( headRotData->headRotEnabled )
+#endif
{
rotateAziEle( ismInput->currentPos.azimuth, ismInput->currentPos.elevation, &azi_rot, &ele_rot, Rmat, 0 );
rotatedPos.azimuth = (float) azi_rot;
@@ -4438,8 +4707,13 @@ static ivas_error renderIsmToBinauralRoom(
}
if ( ( error = getEfapGains( *ismInput->base.ctx.pEfapOutWrapper,
+#ifdef EXTERNAL_ORIENTATIONS
+ ( combinedOrientationEnabled ) ? rotatedPos.azimuth : ismInput->currentPos.azimuth,
+ ( combinedOrientationEnabled ) ? rotatedPos.elevation : ismInput->currentPos.elevation,
+#else
( headRotData->headRotEnabled ) ? rotatedPos.azimuth : ismInput->currentPos.azimuth,
( headRotData->headRotEnabled ) ? rotatedPos.elevation : ismInput->currentPos.elevation,
+#endif
currentPanGains ) ) != IVAS_ERR_OK )
{
return error;
@@ -4730,11 +5004,17 @@ static ivas_error renderMcToBinaural(
const IVAS_REND_AudioConfig outConfig,
IVAS_REND_AudioBuffer outAudio )
{
- int8_t headRotEnabled;
float tmpRendBuffer[MAX_OUTPUT_CHANNELS][L_FRAME48k];
IVAS_REND_AudioConfig inConfig;
ivas_error error;
IVAS_REND_AudioBuffer tmpRotBuffer;
+#ifdef EXTERNAL_ORIENTATIONS
+ const COMBINED_ORIENTATION_HANDLE *hCombinedOrientationData;
+ int8_t combinedOrientationEnabled;
+ int16_t subframe_idx;
+#else
+ int8_t headRotEnabled;
+#endif
float *p_tmpRendBuffer[MAX_OUTPUT_CHANNELS];
int16_t i;
@@ -4745,14 +5025,42 @@ static ivas_error renderMcToBinaural(
push_wmops( "renderMcToBinaural" );
- headRotEnabled = mcInput->base.ctx.pHeadRotData->headRotEnabled;
inConfig = mcInput->base.inConfig;
- if ( ( inConfig == IVAS_REND_AUDIO_CONFIG_LS_CUSTOM ) || ( headRotEnabled && ( inConfig == IVAS_REND_AUDIO_CONFIG_5_1 || inConfig == IVAS_REND_AUDIO_CONFIG_7_1 ) ) )
+#ifdef EXTERNAL_ORIENTATIONS
+ hCombinedOrientationData = mcInput->base.ctx.pCombinedOrientationData;
+ combinedOrientationEnabled = 0;
+ if ( hCombinedOrientationData != NULL )
+ {
+ for ( subframe_idx = 0; subframe_idx < MAX_PARAM_SPATIAL_SUBFRAMES; subframe_idx++ )
+ {
+ if ( ( *hCombinedOrientationData )->enableCombinedOrientation[subframe_idx] != 0 )
+ {
+ combinedOrientationEnabled = 1;
+ break;
+ }
+ }
+ }
+#else
+ headRotEnabled = mcInput->base.ctx.pHeadRotData->headRotEnabled;
+#endif
+
+ if ( ( inConfig == IVAS_REND_AUDIO_CONFIG_LS_CUSTOM ) || (
+#ifdef EXTERNAL_ORIENTATIONS
+ combinedOrientationEnabled
+#else
+ headRotEnabled
+#endif
+
+ && ( inConfig == IVAS_REND_AUDIO_CONFIG_5_1 || inConfig == IVAS_REND_AUDIO_CONFIG_7_1 ) ) )
{
copyBufferTo2dArray( mcInput->base.inputBuffer, tmpRendBuffer );
- if ( ( error = ivas_td_binaural_renderer_ext( &mcInput->tdRendWrapper, mcInput->base.inConfig, &mcInput->customLsInput, mcInput->base.ctx.pHeadRotData, NULL,
+ if ( ( error = ivas_td_binaural_renderer_ext( &mcInput->tdRendWrapper, mcInput->base.inConfig, &mcInput->customLsInput, mcInput->base.ctx.pHeadRotData,
+#ifdef EXTERNAL_ORIENTATIONS
+ mcInput->base.ctx.pCombinedOrientationData,
+#endif
+ NULL,
mcInput->hReverb, mcInput->base.inputBuffer.config.numSamplesPerChannel, tmpRendBuffer ) ) != IVAS_ERR_OK )
{
return error;
@@ -4761,13 +5069,20 @@ static ivas_error renderMcToBinaural(
else
{
/* apply rotation */
+#ifdef EXTERNAL_ORIENTATIONS
+ if ( combinedOrientationEnabled )
+#else
if ( headRotEnabled )
+#endif
{
tmpRotBuffer = mcInput->base.inputBuffer;
tmpRotBuffer.data = malloc( tmpRotBuffer.config.numSamplesPerChannel * tmpRotBuffer.config.numChannels * sizeof( float ) );
set_zero( tmpRotBuffer.data, tmpRotBuffer.config.numSamplesPerChannel * tmpRotBuffer.config.numChannels );
if ( ( error = rotateFrameMc( mcInput->base.inputBuffer, mcInput->base.inConfig, mcInput->customLsInput, mcInput->base.ctx.pHeadRotData,
+#ifdef EXTERNAL_ORIENTATIONS
+ mcInput->base.ctx.pCombinedOrientationData,
+#endif
mcInput->rot_gains_prev, mcInput->efapInWrapper.hEfap, tmpRotBuffer ) ) != IVAS_ERR_OK )
{
return error;
@@ -4806,13 +5121,19 @@ static ivas_error renderMcToBinauralRoom(
const IVAS_REND_AudioConfig outConfig,
IVAS_REND_AudioBuffer outAudio )
{
- int8_t headRotEnabled;
float tmpRendBuffer[MAX_OUTPUT_CHANNELS][L_FRAME48k];
IVAS_REND_AudioConfig inConfig;
ivas_error error;
IVAS_REND_AudioBuffer tmpRotBuffer;
float *p_tmpRendBuffer[MAX_OUTPUT_CHANNELS];
int16_t i;
+#ifdef EXTERNAL_ORIENTATIONS
+ const COMBINED_ORIENTATION_HANDLE *hCombinedOrientationData;
+ int8_t combinedOrientationEnabled;
+ int16_t subframe_idx;
+#else
+ int8_t headRotEnabled;
+#endif
for ( i = 0; i < MAX_OUTPUT_CHANNELS; i++ )
{
@@ -4821,14 +5142,40 @@ static ivas_error renderMcToBinauralRoom(
push_wmops( "renderMcToBinauralRoom" );
- headRotEnabled = mcInput->base.ctx.pHeadRotData->headRotEnabled;
inConfig = mcInput->base.inConfig;
- if ( ( mcInput->hReverb != NULL && mcInput->hReverb->pConfig.roomAcoustics.use_brir == 0 && mcInput->hReverb->pConfig.roomAcoustics.late_reverb_on == 1 ) && ( ( inConfig == IVAS_REND_AUDIO_CONFIG_LS_CUSTOM ) || ( headRotEnabled && ( inConfig == IVAS_REND_AUDIO_CONFIG_5_1 || inConfig == IVAS_REND_AUDIO_CONFIG_7_1 ) ) ) )
+#ifdef EXTERNAL_ORIENTATIONS
+ hCombinedOrientationData = mcInput->base.ctx.pCombinedOrientationData;
+ combinedOrientationEnabled = 0;
+ if ( hCombinedOrientationData != NULL )
+ {
+ for ( subframe_idx = 0; subframe_idx < MAX_PARAM_SPATIAL_SUBFRAMES; subframe_idx++ )
+ {
+ if ( ( *hCombinedOrientationData )->enableCombinedOrientation[subframe_idx] != 0 )
+ {
+ combinedOrientationEnabled = 1;
+ break;
+ }
+ }
+ }
+#else
+ headRotEnabled = mcInput->base.ctx.pHeadRotData->headRotEnabled;
+#endif
+
+ if ( ( mcInput->hReverb != NULL && mcInput->hReverb->pConfig.roomAcoustics.use_brir == 0 && mcInput->hReverb->pConfig.roomAcoustics.late_reverb_on == 1 ) && ( ( inConfig == IVAS_REND_AUDIO_CONFIG_LS_CUSTOM ) || (
+#ifdef EXTERNAL_ORIENTATIONS
+ combinedOrientationEnabled
+#else
+ headRotEnabled
+#endif
+ && ( inConfig == IVAS_REND_AUDIO_CONFIG_5_1 || inConfig == IVAS_REND_AUDIO_CONFIG_7_1 ) ) ) )
{
copyBufferTo2dArray( mcInput->base.inputBuffer, tmpRendBuffer );
if ( ( error = ivas_td_binaural_renderer_ext( &mcInput->tdRendWrapper, mcInput->base.inConfig, &mcInput->customLsInput, mcInput->base.ctx.pHeadRotData,
+#ifdef EXTERNAL_ORIENTATIONS
+ mcInput->base.ctx.pCombinedOrientationData,
+#endif
NULL, mcInput->hReverb, mcInput->base.inputBuffer.config.numSamplesPerChannel, tmpRendBuffer ) ) != IVAS_ERR_OK )
{
return error;
@@ -4837,13 +5184,20 @@ static ivas_error renderMcToBinauralRoom(
else
{
/* apply rotation */
+#ifdef EXTERNAL_ORIENTATIONS
+ if ( combinedOrientationEnabled )
+#else
if ( headRotEnabled )
+#endif
{
tmpRotBuffer = mcInput->base.inputBuffer;
tmpRotBuffer.data = malloc( tmpRotBuffer.config.numSamplesPerChannel * tmpRotBuffer.config.numChannels * sizeof( float ) );
set_zero( tmpRotBuffer.data, tmpRotBuffer.config.numSamplesPerChannel * tmpRotBuffer.config.numChannels );
if ( ( error = rotateFrameMc( mcInput->base.inputBuffer, mcInput->base.inConfig, mcInput->customLsInput, mcInput->base.ctx.pHeadRotData,
+#ifdef EXTERNAL_ORIENTATIONS
+ mcInput->base.ctx.pCombinedOrientationData,
+#endif
mcInput->rot_gains_prev, mcInput->efapInWrapper.hEfap, tmpRotBuffer ) ) != IVAS_ERR_OK )
{
return error;
@@ -4882,7 +5236,6 @@ static ivas_error renderMcCustomLsToBinauralRoom(
const IVAS_REND_AudioConfig outConfig,
IVAS_REND_AudioBuffer outAudio )
{
- int8_t headRotEnabled;
int16_t i;
int16_t tmp;
float tmpCrendBuffer[MAX_OUTPUT_CHANNELS][L_FRAME48k];
@@ -4891,26 +5244,57 @@ static ivas_error renderMcCustomLsToBinauralRoom(
IVAS_REND_AudioBuffer tmpMcBuffer;
IVAS_REND_AudioBuffer *tmpBufPtr;
float *p_tmpCrendBuffer[MAX_OUTPUT_CHANNELS];
+#ifdef EXTERNAL_ORIENTATIONS
+ const COMBINED_ORIENTATION_HANDLE *hCombinedOrientationData;
+ int8_t combinedOrientationEnabled;
+ int16_t subframe_idx;
+#else
+ int8_t headRotEnabled;
+#endif
push_wmops( "renderMcCustomLsToBinauralRoom" );
tmpRotBuffer = outAudio; /* avoid compilation warning */
- headRotEnabled = mcInput->base.ctx.pHeadRotData->headRotEnabled;
-
for ( i = 0; i < MAX_OUTPUT_CHANNELS; i++ )
{
p_tmpCrendBuffer[i] = tmpCrendBuffer[i];
}
+#ifdef EXTERNAL_ORIENTATIONS
+ hCombinedOrientationData = mcInput->base.ctx.pCombinedOrientationData;
+ combinedOrientationEnabled = 0;
+ if ( hCombinedOrientationData != NULL )
+ {
+ for ( subframe_idx = 0; subframe_idx < MAX_PARAM_SPATIAL_SUBFRAMES; subframe_idx++ )
+ {
+ if ( ( *hCombinedOrientationData )->enableCombinedOrientation[subframe_idx] != 0 )
+ {
+ combinedOrientationEnabled = 1;
+ break;
+ }
+ }
+ }
+#else
+ headRotEnabled = mcInput->base.ctx.pHeadRotData->headRotEnabled;
+#endif
+
/* apply rotation */
+#ifdef EXTERNAL_ORIENTATIONS
+ if ( combinedOrientationEnabled )
+#else
if ( headRotEnabled )
+#endif
{
tmpRotBuffer = mcInput->base.inputBuffer;
tmpRotBuffer.data = malloc( tmpRotBuffer.config.numSamplesPerChannel * tmpRotBuffer.config.numChannels * sizeof( float ) );
set_zero( tmpRotBuffer.data, tmpRotBuffer.config.numSamplesPerChannel * tmpRotBuffer.config.numChannels );
- if ( ( error = rotateFrameMc( mcInput->base.inputBuffer, mcInput->base.inConfig, mcInput->customLsInput, mcInput->base.ctx.pHeadRotData, mcInput->rot_gains_prev, mcInput->efapInWrapper.hEfap, tmpRotBuffer ) ) != IVAS_ERR_OK )
+ if ( ( error = rotateFrameMc( mcInput->base.inputBuffer, mcInput->base.inConfig, mcInput->customLsInput, mcInput->base.ctx.pHeadRotData,
+#ifdef EXTERNAL_ORIENTATIONS
+ mcInput->base.ctx.pCombinedOrientationData,
+#endif
+ mcInput->rot_gains_prev, mcInput->efapInWrapper.hEfap, tmpRotBuffer ) ) != IVAS_ERR_OK )
{
return error;
}
@@ -4928,7 +5312,11 @@ static ivas_error renderMcCustomLsToBinauralRoom(
tmpMcBuffer.data = malloc( tmpMcBuffer.config.numSamplesPerChannel * tmpMcBuffer.config.numChannels * sizeof( float ) );
set_zero( tmpMcBuffer.data, tmpMcBuffer.config.numSamplesPerChannel * tmpMcBuffer.config.numChannels );
+#ifdef EXTERNAL_ORIENTATIONS
+ tmpBufPtr = ( combinedOrientationEnabled ) ? &tmpRotBuffer : &mcInput->base.inputBuffer;
+#else
tmpBufPtr = ( headRotEnabled ) ? &tmpRotBuffer : &mcInput->base.inputBuffer;
+#endif
for ( i = 0; i < mcInput->base.inputBuffer.config.numChannels; i++ )
{
renderBufferChannel( *tmpBufPtr, i, mcInput->panGains[i], tmpMcBuffer );
@@ -4949,7 +5337,11 @@ static ivas_error renderMcCustomLsToBinauralRoom(
return error;
}
+#ifdef EXTERNAL_ORIENTATIONS
+ if ( combinedOrientationEnabled )
+#else
if ( headRotEnabled )
+#endif
{
free( tmpRotBuffer.data );
}
@@ -5139,6 +5531,11 @@ static ivas_error renderSbaToBinaural(
IVAS_REND_AudioBuffer tmpRotBuffer;
float *p_tmpCrendBuffer[MAX_OUTPUT_CHANNELS];
int16_t i;
+#ifdef EXTERNAL_ORIENTATIONS
+ const COMBINED_ORIENTATION_HANDLE *hCombinedOrientationData;
+ int8_t combinedOrientationEnabled;
+ int16_t subframe_idx;
+#endif
push_wmops( "renderSbaToBinaural" );
@@ -5147,8 +5544,28 @@ static ivas_error renderSbaToBinaural(
p_tmpCrendBuffer[i] = tmpCrendBuffer[i];
}
+#ifdef EXTERNAL_ORIENTATIONS
+ hCombinedOrientationData = sbaInput->base.ctx.pCombinedOrientationData;
+ combinedOrientationEnabled = 0;
+ if ( hCombinedOrientationData != NULL )
+ {
+ for ( subframe_idx = 0; subframe_idx < MAX_PARAM_SPATIAL_SUBFRAMES; subframe_idx++ )
+ {
+ if ( ( *hCombinedOrientationData )->enableCombinedOrientation[subframe_idx] != 0 )
+ {
+ combinedOrientationEnabled = 1;
+ break;
+ }
+ }
+ }
+#endif
+
/* apply rotation */
+#ifdef EXTERNAL_ORIENTATIONS
+ if ( combinedOrientationEnabled )
+#else
if ( sbaInput->base.ctx.pHeadRotData->headRotEnabled )
+#endif
{
tmpRotBuffer = sbaInput->base.inputBuffer;
tmpRotBuffer.data = malloc( tmpRotBuffer.config.numSamplesPerChannel * tmpRotBuffer.config.numChannels * sizeof( float ) );
@@ -5156,7 +5573,11 @@ static ivas_error renderSbaToBinaural(
/* copy input for in-place rotation */
mvr2r( sbaInput->base.inputBuffer.data, tmpRotBuffer.data, tmpRotBuffer.config.numChannels * tmpRotBuffer.config.numSamplesPerChannel );
- if ( ( error = rotateFrameSba( sbaInput->base.inputBuffer, sbaInput->base.inConfig, sbaInput->base.ctx.pHeadRotData, sbaInput->rot_gains_prev, tmpRotBuffer ) ) != IVAS_ERR_OK )
+ if ( ( error = rotateFrameSba( sbaInput->base.inputBuffer, sbaInput->base.inConfig, sbaInput->base.ctx.pHeadRotData,
+#ifdef EXTERNAL_ORIENTATIONS
+ sbaInput->base.ctx.pCombinedOrientationData,
+#endif
+ sbaInput->rot_gains_prev, tmpRotBuffer ) ) != IVAS_ERR_OK )
{
return error;
}
@@ -5188,7 +5609,6 @@ static ivas_error renderSbaToBinauralRoom(
const IVAS_REND_AudioConfig outConfig,
IVAS_REND_AudioBuffer outAudio )
{
- int8_t headRotEnabled;
int16_t i;
int16_t tmp;
float tmpCrendBuffer[MAX_OUTPUT_CHANNELS][L_FRAME48k];
@@ -5197,6 +5617,13 @@ static ivas_error renderSbaToBinauralRoom(
IVAS_REND_AudioBuffer tmpMcBuffer;
IVAS_REND_AudioBuffer *tmpBufPtr;
float *p_tmpCrendBuffer[MAX_OUTPUT_CHANNELS];
+#ifdef EXTERNAL_ORIENTATIONS
+ const COMBINED_ORIENTATION_HANDLE *hCombinedOrientationData;
+ int8_t combinedOrientationEnabled;
+ int16_t subframe_idx;
+#else
+ int8_t headRotEnabled;
+#endif
tmpRotBuffer = outAudio; /* avoid compilation warning */
@@ -5207,10 +5634,30 @@ static ivas_error renderSbaToBinauralRoom(
p_tmpCrendBuffer[i] = tmpCrendBuffer[i];
}
+#ifdef EXTERNAL_ORIENTATIONS
+ hCombinedOrientationData = sbaInput->base.ctx.pCombinedOrientationData;
+ combinedOrientationEnabled = 0;
+ if ( hCombinedOrientationData != NULL )
+ {
+ for ( subframe_idx = 0; subframe_idx < MAX_PARAM_SPATIAL_SUBFRAMES; subframe_idx++ )
+ {
+ if ( ( *hCombinedOrientationData )->enableCombinedOrientation[subframe_idx] != 0 )
+ {
+ combinedOrientationEnabled = 1;
+ break;
+ }
+ }
+ }
+#else
headRotEnabled = sbaInput->base.ctx.pHeadRotData->headRotEnabled;
+#endif
/* apply rotation */
+#ifdef EXTERNAL_ORIENTATIONS
+ if ( combinedOrientationEnabled )
+#else
if ( headRotEnabled )
+#endif
{
tmpRotBuffer = sbaInput->base.inputBuffer;
tmpRotBuffer.data = malloc( tmpRotBuffer.config.numSamplesPerChannel * tmpRotBuffer.config.numChannels * sizeof( float ) );
@@ -5218,7 +5665,11 @@ static ivas_error renderSbaToBinauralRoom(
/* copy input for in-place rotation */
mvr2r( sbaInput->base.inputBuffer.data, tmpRotBuffer.data, tmpRotBuffer.config.numChannels * tmpRotBuffer.config.numSamplesPerChannel );
- if ( ( error = rotateFrameSba( sbaInput->base.inputBuffer, sbaInput->base.inConfig, sbaInput->base.ctx.pHeadRotData, sbaInput->rot_gains_prev, tmpRotBuffer ) ) != IVAS_ERR_OK )
+ if ( ( error = rotateFrameSba( sbaInput->base.inputBuffer, sbaInput->base.inConfig, sbaInput->base.ctx.pHeadRotData,
+#ifdef EXTERNAL_ORIENTATIONS
+ sbaInput->base.ctx.pCombinedOrientationData,
+#endif
+ sbaInput->rot_gains_prev, tmpRotBuffer ) ) != IVAS_ERR_OK )
{
return error;
}
@@ -5236,7 +5687,11 @@ static ivas_error renderSbaToBinauralRoom(
tmpMcBuffer.data = malloc( tmpMcBuffer.config.numSamplesPerChannel * tmpMcBuffer.config.numChannels * sizeof( float ) );
set_zero( tmpMcBuffer.data, tmpMcBuffer.config.numChannels * tmpMcBuffer.config.numSamplesPerChannel );
+#ifdef EXTERNAL_ORIENTATIONS
+ tmpBufPtr = ( combinedOrientationEnabled ) ? &tmpRotBuffer : &sbaInput->base.inputBuffer;
+#else
tmpBufPtr = ( headRotEnabled ) ? &tmpRotBuffer : &sbaInput->base.inputBuffer;
+#endif
for ( i = 0; i < sbaInput->base.inputBuffer.config.numChannels; i++ )
{
renderBufferChannel( *tmpBufPtr, i, sbaInput->hoaDecMtx[i], tmpMcBuffer );
@@ -5253,7 +5708,11 @@ static ivas_error renderSbaToBinauralRoom(
accumulate2dArrayToBuffer( tmpCrendBuffer, &outAudio );
+#ifdef EXTERNAL_ORIENTATIONS
+ if ( combinedOrientationEnabled )
+#else
if ( headRotEnabled )
+#endif
{
free( tmpRotBuffer.data );
}
@@ -5394,7 +5853,11 @@ static void renderMasaToMc(
if ( masaInput->decDummy->renderer_type == RENDERER_STEREO_PARAMETRIC )
{
+#ifdef EXTERNAL_ORIENTATIONS
+ ivas_dirac_dec_binaural( masaInput->decDummy, *masaInput->base.ctx.pCombinedOrientationData, tmpBuffer, masaInput->base.inputBuffer.config.numChannels );
+#else
ivas_dirac_dec_binaural( masaInput->decDummy, tmpBuffer, masaInput->base.inputBuffer.config.numChannels );
+#endif
}
else
{
@@ -5431,7 +5894,11 @@ static void renderMasaToBinaural(
copyBufferTo2dArray( masaInput->base.inputBuffer, tmpBuffer );
copyMasaMetadataToDiracRenderer( &masaInput->masaMetadata, masaInput->decDummy->hDirAC );
+#ifdef EXTERNAL_ORIENTATIONS
+ ivas_dirac_dec_binaural( masaInput->decDummy, *masaInput->base.ctx.pCombinedOrientationData, tmpBuffer, masaInput->base.inputBuffer.config.numChannels );
+#else
ivas_dirac_dec_binaural( masaInput->decDummy, tmpBuffer, masaInput->base.inputBuffer.config.numChannels );
+#endif
accumulate2dArrayToBuffer( tmpBuffer, &outAudio );
@@ -5649,6 +6116,11 @@ void IVAS_REND_Close(
closeHeadRotation( hIvasRend );
+#ifdef EXTERNAL_ORIENTATIONS
+ ivas_external_orientation_close( &hIvasRend->hExternalOrientationData );
+ ivas_combined_orientation_close( &hIvasRend->hCombinedOrientationData );
+#endif
+
free( hIvasRend );
*phIvasRend = NULL;
diff --git a/lib_rend/lib_rend.h b/lib_rend/lib_rend.h
index cf0db7e4b5139552032bb021664a55124354c1ac..406fa83e8744c59875aa19743944c0d6172ede27 100644
--- a/lib_rend/lib_rend.h
+++ b/lib_rend/lib_rend.h
@@ -275,6 +275,26 @@ ivas_error IVAS_REND_SetReferenceVector(
const IVAS_VECTOR3 refPos /* i : Reference position */
);
+#ifdef EXTERNAL_ORIENTATIONS
+ivas_error IVAS_REND_SetExternalOrientation(
+ IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */
+ IVAS_QUATERNION *orientation, /* i : external orientation data */
+ int8_t *enableHeadRotation, /* i : flag to enable head rotation for this frame */
+ int8_t *enableExternalOrientation, /* i : flag to enable external orientation for this frame */
+ int8_t *enableRotationInterpolation, /* i : flag to interpolate rotations from current and previous frames */
+ int16_t *numFramesToTargetOrientation /* i : number of frames until target orientation is reached */
+);
+
+ivas_error IVAS_REND_CombineHeadAndExternalOrientation(
+ IVAS_REND_HANDLE hIvasRend /* i/o: Renderer handle */
+);
+
+ivas_error IVAS_REND_GetCombinedOrientation(
+ IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */
+ IVAS_QUATERNION *pRotation /* i/o: Quaternion pointer processed orientation */
+);
+#endif
+
ivas_error IVAS_REND_GetSamples(
IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */
IVAS_REND_AudioBuffer outAudio /* i/o: buffer for output audio */
diff --git a/lib_util/head_rotation_file_reader.c b/lib_util/head_rotation_file_reader.c
index 0283c292334daec7e88a2ffa6f54eb790f455257..3fd6e4f4395bbe1ebdac6d97c8d33570f82729d6 100644
--- a/lib_util/head_rotation_file_reader.c
+++ b/lib_util/head_rotation_file_reader.c
@@ -36,6 +36,8 @@
#include
#include "prot.h"
+#ifndef EXTERNAL_ORIENTATIONS
+
struct HeadRotFileReader
{
FILE *trajFile;
@@ -175,3 +177,5 @@ const char *HeadRotationFileReader_getFilePath(
return headRotReader->file_path;
}
+
+#endif /* EXTERNAL_ORIENTATIONS */
diff --git a/lib_util/head_rotation_file_reader.h b/lib_util/head_rotation_file_reader.h
index 52b97ae1c3db0417fb308b47b484bb0b11feea61..3c82f06403d25a5d5382e96261d832ec310328ff 100644
--- a/lib_util/head_rotation_file_reader.h
+++ b/lib_util/head_rotation_file_reader.h
@@ -35,6 +35,7 @@
#include "common_api_types.h"
+#ifndef EXTERNAL_ORIENTATIONS
#define IVAS_MAX_PARAM_SPATIAL_SUBFRAMES 4
@@ -84,4 +85,5 @@ const char *HeadRotationFileReader_getFilePath(
);
+#endif /* EXTERNAL_ORIENTATIONS */
#endif /* IVAS_HR_FILE_READER_H */
diff --git a/lib_util/rotation_file_reader.c b/lib_util/rotation_file_reader.c
new file mode 100644
index 0000000000000000000000000000000000000000..42bd6a3ed5910dc9f2671aff8d6d260211ea6406
--- /dev/null
+++ b/lib_util/rotation_file_reader.c
@@ -0,0 +1,235 @@
+/******************************************************************************************************
+
+ (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
+ Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+ Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+ Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+ contributors to this repository. All Rights Reserved.
+
+ This software is protected by copyright law and by international treaties.
+ The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
+ Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+ Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+ Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+ contributors to this repository retain full ownership rights in their respective contributions in
+ the software. This notice grants no license of any kind, including but not limited to patent
+ license, nor is any license granted by implication, estoppel or otherwise.
+
+ Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
+ contributions.
+
+ This software is provided "AS IS", without any express or implied warranties. The software is in the
+ development stage. It is intended exclusively for experts who have experience with such software and
+ solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
+ and fitness for a particular purpose are hereby disclaimed and excluded.
+
+ Any dispute, controversy or claim arising under or in relation to providing this software shall be
+ submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
+ accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
+ the United Nations Convention on Contracts on the International Sales of Goods.
+
+*******************************************************************************************************/
+
+#include "rotation_file_reader.h"
+#include
+#include
+#include
+#include "prot.h"
+
+#ifdef EXTERNAL_ORIENTATIONS
+
+struct RotFileReader
+{
+ FILE *trajFile;
+ int32_t frameCounter;
+ char *file_path;
+ bool fileRewind;
+};
+
+
+/*-----------------------------------------------------------------------*
+ * RotationFileReader_open()
+ *
+ * Allocate and initialize rotation reader
+ *-----------------------------------------------------------------------*/
+
+ivas_error RotationFileReader_open(
+ char *trajFilePath, /* i : rotation trajectory file name */
+ RotFileReader **rotReader /* o : RotFileReader handle */
+)
+{
+ RotFileReader *self;
+ FILE *trajFile;
+
+ /* Open trajectory file */
+ if ( strlen( trajFilePath ) < 1 )
+ {
+ return IVAS_ERR_FAILED_FILE_OPEN;
+ }
+
+ trajFile = fopen( trajFilePath, "r" );
+
+ if ( !trajFile )
+ {
+ return IVAS_ERR_FAILED_FILE_OPEN;
+ }
+
+ self = calloc( sizeof( RotFileReader ), 1 );
+ self->trajFile = trajFile;
+ self->frameCounter = 0;
+ self->file_path = calloc( sizeof( char ), strlen( trajFilePath ) + 1 );
+ strcpy( self->file_path, trajFilePath );
+ self->fileRewind = false;
+
+ *rotReader = self;
+
+ return IVAS_ERR_OK;
+}
+
+
+/*-----------------------------------------------------------------------*
+ * HeadRotationFileReading()
+ *
+ * Read values from the trajectory file
+ *-----------------------------------------------------------------------*/
+
+ivas_error HeadRotationFileReading(
+ RotFileReader *headRotReader, /* i/o: HeadRotFileReader handle */
+ IVAS_QUATERNION *pQuaternion, /* o : head-tracking data */
+ IVAS_VECTOR3 *pPos /* o : listener position */
+)
+{
+ float w, x, y, z;
+ float posx, posy, posz;
+ int32_t read_values;
+
+ posx = 0.0f;
+ posy = 0.0f;
+ posz = 0.0f;
+
+ 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) */
+ {
+ if ( feof( headRotReader->trajFile ) )
+ {
+ rewind( headRotReader->trajFile );
+ headRotReader->fileRewind = true;
+ return HeadRotationFileReading( headRotReader, pQuaternion, pPos );
+ }
+ return IVAS_ERR_FAILED_FILE_PARSE;
+ }
+
+ ( headRotReader->frameCounter )++;
+
+ pQuaternion->w = w;
+ pQuaternion->x = x;
+ pQuaternion->y = y;
+ pQuaternion->z = z;
+ if ( pPos != NULL )
+ {
+ pPos->x = posx;
+ pPos->y = posy;
+ pPos->z = posz;
+ }
+
+ return IVAS_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------*
+ * ExternalOrientationFileReading()
+ *
+ * Read values from the trajectory file
+ *-----------------------------------------------------------------------*/
+
+ivas_error ExternalOrientationFileReading(
+ RotFileReader *externalOrientationReader, /* i/o: ExternalOrientationReader handle */
+ IVAS_QUATERNION *pQuaternion, /* o : external orientation data */
+ int8_t *enableHeadRotation, /* o : flag to enable head rotation for this frame */
+ int8_t *enableExternalOrientation, /* o : flag to enable external orientation for this frame */
+ int8_t *enableRotationInterpolation, /* o : flag to enable interpolation between the current and target orientations */
+ int16_t *numFramesToTargetOrientation /* o : number of frames until target orientation is reached */
+)
+{
+ float w, x, y, z;
+ float headRotFlag;
+ float extOrientationFlag;
+ float rotInterpolationFlag;
+ float nFramesToTarget;
+ int32_t read_values;
+
+ /* Initial values, if they are not read from the file */
+ headRotFlag = 1;
+ extOrientationFlag = 1;
+ rotInterpolationFlag = 0;
+ nFramesToTarget = 0;
+
+ read_values = fscanf( externalOrientationReader->trajFile, "%f,%f,%f,%f,%f,%f,%f,%f", &w, &x, &y, &z, &headRotFlag, &extOrientationFlag, &rotInterpolationFlag, &nFramesToTarget );
+ if ( ( read_values != 4 ) && ( read_values != 5 ) && ( read_values != 6 ) && ( read_values != 7 ) && ( read_values != 8 ) ) /* Allow either orientation (4) OR orientation + headRotationFlag (5) OR orientation + headRotationFlag + extOrientationFlag (6) OR orientation + headRotationFlag + extOrientationFlag + rotInterpolationFlag (7) OR orientation + headRotationFlag + extOrientationFlag + rotInterpolationFlag + number of frames to target (8) */
+ {
+ if ( feof( externalOrientationReader->trajFile ) )
+ {
+ rewind( externalOrientationReader->trajFile );
+ externalOrientationReader->fileRewind = true;
+ return ExternalOrientationFileReading( externalOrientationReader, pQuaternion, enableHeadRotation, enableExternalOrientation, enableRotationInterpolation, numFramesToTargetOrientation );
+ }
+ return IVAS_ERR_FAILED_FILE_PARSE;
+ }
+
+ ( externalOrientationReader->frameCounter )++;
+
+ pQuaternion->w = w;
+ pQuaternion->x = x;
+ pQuaternion->y = y;
+ pQuaternion->z = z;
+ *enableHeadRotation = (int8_t) headRotFlag;
+ *enableExternalOrientation = (int8_t) extOrientationFlag;
+ *enableRotationInterpolation = (int8_t) rotInterpolationFlag;
+ *numFramesToTargetOrientation = (int16_t) nFramesToTarget;
+
+ return IVAS_ERR_OK;
+}
+
+
+/*-----------------------------------------------------------------------*
+ * RotationFileReader_close()
+ *
+ * Deallocates memory for the rotation reader
+ *-----------------------------------------------------------------------*/
+
+void RotationFileReader_close(
+ RotFileReader **rotReader /* i/o: RotFileReader handle */
+)
+{
+ if ( rotReader == NULL || *rotReader == NULL )
+ {
+ return;
+ }
+
+ fclose( ( *rotReader )->trajFile );
+ free( ( *rotReader )->file_path );
+ free( *rotReader );
+ *rotReader = NULL;
+
+ return;
+}
+
+
+/*-----------------------------------------------------------------------*
+ * HeadRotationFileReader_getFilePath()
+ *
+ *
+ *-----------------------------------------------------------------------*/
+
+const char *RotationFileReader_getFilePath(
+ RotFileReader *rotReader /* i/o: RotFileReader handle */
+)
+{
+ if ( rotReader == NULL )
+ {
+ return NULL;
+ }
+
+ return rotReader->file_path;
+}
+
+#endif /* EXTERNAL_ORIENTATIONS */
diff --git a/lib_util/rotation_file_reader.h b/lib_util/rotation_file_reader.h
new file mode 100644
index 0000000000000000000000000000000000000000..5f32f4ca0974c4caf4f40e524bde71b2faf59cd2
--- /dev/null
+++ b/lib_util/rotation_file_reader.h
@@ -0,0 +1,104 @@
+/******************************************************************************************************
+
+ (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
+ Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+ Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+ Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+ contributors to this repository. All Rights Reserved.
+
+ This software is protected by copyright law and by international treaties.
+ The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
+ Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+ Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+ Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+ contributors to this repository retain full ownership rights in their respective contributions in
+ the software. This notice grants no license of any kind, including but not limited to patent
+ license, nor is any license granted by implication, estoppel or otherwise.
+
+ Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
+ contributions.
+
+ This software is provided "AS IS", without any express or implied warranties. The software is in the
+ development stage. It is intended exclusively for experts who have experience with such software and
+ solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
+ and fitness for a particular purpose are hereby disclaimed and excluded.
+
+ Any dispute, controversy or claim arising under or in relation to providing this software shall be
+ submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
+ accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
+ the United Nations Convention on Contracts on the International Sales of Goods.
+
+*******************************************************************************************************/
+
+#ifndef IVAS_ROTATION_FILE_READER_H
+#define IVAS_ROTATION_FILE_READER_H
+
+#include "common_api_types.h"
+
+#ifdef EXTERNAL_ORIENTATIONS
+
+#define IVAS_MAX_PARAM_SPATIAL_SUBFRAMES 4
+
+typedef struct RotFileReader RotFileReader;
+
+/*-----------------------------------------------------------------------*
+ * RotationFileReader_open()
+ *
+ * Allocate and initialize rotation handle
+ *-----------------------------------------------------------------------*/
+
+ivas_error RotationFileReader_open(
+ char *trajFilePath, /* i : rotation trajectory file name */
+ RotFileReader **rotReader /* o : RotFileReader handle */
+);
+
+/*-----------------------------------------------------------------------*
+ * RotationFileReading()
+ *
+ * Read values from the trajectory file
+ *-----------------------------------------------------------------------*/
+
+ivas_error HeadRotationFileReading(
+ RotFileReader *headRotReader, /* i/o: RotFileReader handle */
+ IVAS_QUATERNION *pQuaternion, /* o : head-tracking data */
+ IVAS_VECTOR3 *pPos /* o : listener position */
+);
+
+/*-----------------------------------------------------------------------*
+ * ExternalOrientationFileReading()
+ *
+ * Read values from the trajectory file
+ *-----------------------------------------------------------------------*/
+
+ivas_error ExternalOrientationFileReading(
+ RotFileReader *externalOrientationReader, /* i/o: RotFileReader handle */
+ IVAS_QUATERNION *pQuaternion, /* o : external orientation data */
+ int8_t *enableHeadRotation, /* o : flag to enable head rotation for this frame */
+ int8_t *enableExternalOrientation, /* o : flag to enable external orientation for this frame */
+ int8_t *enableRotationInterpolation, /* o : flag to enable interpolation between the current and target orientations */
+ int16_t *numFramesToTargetOrientation /* o : number of frames until target orientation is achieved */
+);
+
+/*-----------------------------------------------------------------------*
+ * RotationFileReader_close()
+ *
+ * Deallocates memory for the rotation handle
+ *-----------------------------------------------------------------------*/
+
+void RotationFileReader_close(
+ RotFileReader **rotReader /* i/o: RotFileReader handle */
+);
+
+/*-----------------------------------------------------------------------*
+ * RotationFileReader_getFilePath()
+ *
+ *
+ *-----------------------------------------------------------------------*/
+
+const char *RotationFileReader_getFilePath(
+ RotFileReader *rotReader /* i/o: RotFileReader handle */
+);
+
+
+#endif /* EXTERNAL_ORIENTATIONS */
+#endif /* IVAS_ROTATION_FILE_READER_H */