From 23edae7f2e78b61daa753bf7c19f7d656f56e9ea Mon Sep 17 00:00:00 2001 From: Lauros Pajunen Date: Fri, 7 Nov 2025 12:07:00 +0200 Subject: [PATCH 1/4] Implement reverse direction ISM PI --- lib_com/options.h | 1 + lib_util/ivas_rtp_file.c | 39 +++++ lib_util/ivas_rtp_internal.h | 3 + lib_util/ivas_rtp_pi_data.c | 267 ++++++++++++++++++++++++++++++++++- lib_util/ivas_rtp_pi_data.h | 30 +++- tests/rtp/ivasrtp.py | 77 +++++++++- tests/rtp/test_rtp.py | 30 +++- 7 files changed, 437 insertions(+), 10 deletions(-) diff --git a/lib_com/options.h b/lib_com/options.h index 6d7fec9389..dac98a4037 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -164,6 +164,7 @@ #define FIXED_RTP_SEQUENCE_NUM /* Remove random sequence number initialization */ #define ISM_PI_DATA /* Add reading and packing/unpacking of ISM PI data */ #define PI_DATA_FIX /* Fix for PI Data JSON file */ +#define REVERSE_ISM_PI_DATA /* Add reading and packing/unpacking of reverse ISM PI data */ /* ################### Start BE switches ################################# */ /* only BE switches wrt selection floating point code */ diff --git a/lib_util/ivas_rtp_file.c b/lib_util/ivas_rtp_file.c index d3ba0a63b1..48d788ceba 100644 --- a/lib_util/ivas_rtp_file.c +++ b/lib_util/ivas_rtp_file.c @@ -195,7 +195,9 @@ void IVAS_RTP_LogPiData( #ifdef RTP_S4_251135_CR26253_0016_REV1 case IVAS_PI_PLAYBACK_DEVICE_ORIENTATION: case IVAS_PI_HEAD_ORIENTATION: +#ifndef REVERSE_ISM_PI_DATA case IVAS_PI_R_ISM_ORIENTATION: +#endif #endif { fprintf( f_piDataOut, "{\n\t\t\t\"w\": %f,\n\t\t\t\"x\": %f,\n\t\t\t\"y\": %f,\n\t\t\t\"z\": %f \n\t\t}", @@ -221,7 +223,9 @@ void IVAS_RTP_LogPiData( break; #ifdef RTP_S4_251135_CR26253_0016_REV1 case IVAS_PI_LISTENER_POSITION: +#ifndef REVERSE_ISM_PI_DATA case IVAS_PI_R_ISM_POSITION: +#endif { fprintf( f_piDataOut, "{\n\t\t\t\"x\": %f,\n\t\t\t\"y\": %f,\n\t\t\t\"z\": %f \n\t\t}", cur->data.listnerPosition.position.x, cur->data.listnerPosition.position.y, cur->data.listnerPosition.position.z ); @@ -439,8 +443,43 @@ void IVAS_RTP_LogPiData( #endif case IVAS_PI_PI_LATENCY: case IVAS_PI_R_ISM_ID: +#ifdef REVERSE_ISM_PI_DATA + { + fprintf( f_piDataOut, "{\n" ); + fprintf( f_piDataOut, "\t\t\t\"id\": %d", cur->data.ismEditId.id ); + fprintf( f_piDataOut, "\n\t\t}" ); + } + break; +#endif case IVAS_PI_R_ISM_GAIN: +#ifdef REVERSE_ISM_PI_DATA + { + fprintf( f_piDataOut, "{\n" ); + fprintf( f_piDataOut, "\t\t\t\"gain\": %d", cur->data.ismEditGain.dB ); + fprintf( f_piDataOut, "\n\t\t}" ); + } + break; + case IVAS_PI_R_ISM_ORIENTATION: + { + fprintf( f_piDataOut, "{\n\t\t\t\"w\": %f,\n\t\t\t\"x\": %f,\n\t\t\t\"y\": %f,\n\t\t\t\"z\": %f \n\t\t}", + cur->data.ismEditOrientation.orientation.w, cur->data.ismEditOrientation.orientation.x, cur->data.ismEditOrientation.orientation.y, cur->data.ismEditOrientation.orientation.z ); + } + break; + case IVAS_PI_R_ISM_POSITION: + { + fprintf( f_piDataOut, "{\n\t\t\t\"x\": %f,\n\t\t\t\"y\": %f,\n\t\t\t\"z\": %f \n\t\t}", + cur->data.ismEditPosition.position.x, cur->data.ismEditPosition.position.y, cur->data.ismEditPosition.position.z ); + } + break; +#endif case IVAS_PI_R_ISM_DIRECTION: +#ifdef REVERSE_ISM_PI_DATA + { + fprintf( f_piDataOut, "{\n\t\t\t\"azi\": %f,\n\t\t\t\"elev\": %f \n\t\t}", + cur->data.ismEditDirection.azimuth, cur->data.ismEditDirection.elevation ); + } + break; +#endif #endif /* RTP_S4_251135_CR26253_0016_REV1 */ case IVAS_PI_NO_DATA: { diff --git a/lib_util/ivas_rtp_internal.h b/lib_util/ivas_rtp_internal.h index 08d01a4ebc..1811ab7b65 100644 --- a/lib_util/ivas_rtp_internal.h +++ b/lib_util/ivas_rtp_internal.h @@ -48,6 +48,9 @@ enum MASK_BITS MASK_6BIT = 0x3F, MASK_7BIT = 0x7F, MASK_8BIT = 0xFF, +#ifdef REVERSE_ISM_PI_DATA + MASK_9BIT = 0x1FF, +#endif }; diff --git a/lib_util/ivas_rtp_pi_data.c b/lib_util/ivas_rtp_pi_data.c index ad8a507355..ef84daf20f 100644 --- a/lib_util/ivas_rtp_pi_data.c +++ b/lib_util/ivas_rtp_pi_data.c @@ -32,6 +32,9 @@ #include "ivas_error_utils.h" #include "ivas_rtp_internal.h" +#ifdef REVERSE_ISM_PI_DATA +#include +#endif #ifdef ISM_PI_DATA #include @@ -510,6 +513,56 @@ static ivas_error unpackDynamicSuppression( const uint8_t *buffer, uint32_t numD return IVAS_ERR_OK; } +#ifdef REVERSE_ISM_PI_DATA +static ivas_error packPosition( const IVAS_PIDATA_GENERIC *piData, uint8_t *buffer, uint32_t maxDataBytes, uint32_t *nBytesWritten ) +{ + uint32_t nBytes = 0; + const IVAS_PIDATA_POSITION *position = (const IVAS_PIDATA_POSITION *) piData; + + *nBytesWritten = 0; + + if ( piData->size != sizeof( IVAS_PIDATA_POSITION ) ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect size in position PI data" ); + } + + if ( piData->piDataType != IVAS_PI_LISTENER_POSITION && piData->piDataType != IVAS_PI_R_ISM_POSITION ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect PI ID in position PI data" ); + } + + /* Position data is 6 bytes, header is 2 bytes */ + if ( maxDataBytes < 6 + 2 ) + { + return IVAS_ERROR( IVAS_ERR_RTP_INSUFFICIENT_OUTPUT_SIZE, "Insufficient space to pack position PI data" ); + } + + buffer[nBytes++] = ( position->piDataType & MASK_5BIT ); /* PF/PM populated during final packing */ + buffer[nBytes++] = 6; + nBytes = writeInt16( buffer, nBytes, ivasPayload_convertToQ15( position->position.x / MAX_PI_POSITION_METERS ) ); + nBytes = writeInt16( buffer, nBytes, ivasPayload_convertToQ15( position->position.y / MAX_PI_POSITION_METERS ) ); + nBytes = writeInt16( buffer, nBytes, ivasPayload_convertToQ15( position->position.z / MAX_PI_POSITION_METERS ) ); + *nBytesWritten = nBytes; + return IVAS_ERR_OK; +} + +static ivas_error unpackPosition( const uint8_t *buffer, uint32_t numDataBytes, IVAS_PIDATA_GENERIC *piData ) +{ + IVAS_PIDATA_POSITION *position = (IVAS_PIDATA_POSITION *) piData; + + /* Position data is 6 bytes */ + if ( numDataBytes != 6 ) + { + return IVAS_ERROR( IVAS_ERR_RTP_UNPACK_PI_DATA, "Incorrect size to unpack position PI data" ); + } + + position->size = sizeof( IVAS_PIDATA_POSITION ); + position->position.x = FLOAT_FROM_Q15( readInt16( &buffer[0] ) ) * MAX_PI_POSITION_METERS; + position->position.y = FLOAT_FROM_Q15( readInt16( &buffer[2] ) ) * MAX_PI_POSITION_METERS; + position->position.z = FLOAT_FROM_Q15( readInt16( &buffer[4] ) ) * MAX_PI_POSITION_METERS; + return IVAS_ERR_OK; +} +#else static ivas_error packListenerPosition( const IVAS_PIDATA_GENERIC *piData, uint8_t *buffer, uint32_t maxDataBytes, uint32_t *nBytesWritten ) { uint32_t nBytes = 0; @@ -559,6 +612,7 @@ static ivas_error unpackListenerPosition( const uint8_t *buffer, uint32_t numDat listener->position.z = FLOAT_FROM_Q15( readInt16( &buffer[4] ) ) * MAX_PI_POSITION_METERS; return IVAS_ERR_OK; } +#endif #ifdef ISM_PI_DATA static ivas_error packISMPosition( const IVAS_PIDATA_GENERIC *piData, uint8_t *buffer, uint32_t maxDataBytes, uint32_t *nBytesWritten ) @@ -1144,6 +1198,189 @@ static ivas_error unpackISMDirectivity( const uint8_t *buffer, uint32_t numDataB } #endif +#ifdef REVERSE_ISM_PI_DATA +static ivas_error packReverseISMID( const IVAS_PIDATA_GENERIC *piData, uint8_t *buffer, uint32_t maxDataBytes, uint32_t *nBytesWritten ) +{ + uint32_t nBytes = 0, n; + const IVAS_PIDATA_ISM_EDIT_ID *r_ism_id = (const IVAS_PIDATA_ISM_EDIT_ID *) piData; + + *nBytesWritten = 0; + + if ( piData->size > sizeof( IVAS_PIDATA_ISM_EDIT_ID ) ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect size in R_ISM_ID PI data" ); + } + + if ( piData->piDataType != IVAS_PI_R_ISM_ID ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect PI ID in R_ISM_ID PI data" ); + } + + /* R_ISM_ID data is 1 byte, header is 2 bytes */ + if ( maxDataBytes < 1 + 2 ) + { + return IVAS_ERROR( IVAS_ERR_RTP_INSUFFICIENT_OUTPUT_SIZE, "Insufficient space to pack R_ISM_NUM PI data" ); + } + + buffer[nBytes++] = ( r_ism_id->piDataType & MASK_5BIT ); /* PF/PM populated during final packing */ + buffer[nBytes++] = ( r_ism_id->id & MASK_8BIT ); + *nBytesWritten = nBytes; + return IVAS_ERR_OK; +} + +static ivas_error unpackReverseISMID( const uint8_t *buffer, uint32_t numDataBytes, IVAS_PIDATA_GENERIC *piData ) +{ + uint32_t n; + IVAS_PIDATA_ISM_EDIT_ID *r_ism_id = (IVAS_PIDATA_ISM_EDIT_ID *) piData; + + /* ISM_ID data is 1 byte*/ + if ( numDataBytes > 1 ) + { + return IVAS_ERROR( IVAS_ERR_RTP_UNPACK_PI_DATA, "Incorrect size to unpack R_ISM_ID PI data" ); + } + + r_ism_id->size = sizeof( IVAS_PIDATA_ISM_EDIT_ID ); + r_ism_id->piDataType = IVAS_PI_R_ISM_ID; + r_ism_id->id = *buffer; + + return IVAS_ERR_OK; +} + +static ivas_error packReverseISMGain( const IVAS_PIDATA_GENERIC *piData, uint8_t *buffer, uint32_t maxDataBytes, uint32_t *nBytesWritten ) +{ + uint32_t nBytes = 0, idx; + int16_t gain; + const IVAS_PIDATA_ISM_EDIT_GAIN *r_ism_gain = (const IVAS_PIDATA_ISM_EDIT_GAIN *) piData; + + *nBytesWritten = 0; + + if ( piData->size > sizeof( IVAS_PIDATA_ISM_EDIT_GAIN ) ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect size in R_ISM_GAIN PI data" ); + } + + if ( piData->piDataType != IVAS_PI_R_ISM_GAIN ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect PI ID in R_ISM_GAIN PI data" ); + } + + /* R_ISM_GAIN data is 1 byte, header is 2 bytes */ + if ( maxDataBytes < 1 + 2 ) + { + return IVAS_ERROR( IVAS_ERR_RTP_INSUFFICIENT_OUTPUT_SIZE, "Insufficient space to pack R_ISM_GAIN PI data" ); + } + + buffer[nBytes++] = ( r_ism_gain->piDataType & MASK_5BIT ); /* PF/PM populated during final packing */ + gain = (int16_t) r_ism_gain->dB; + idx = min( -gain, 97 ); + if ( gain > 0 ) + { + idx += 97; + } + + buffer[nBytes++] = ( idx & MASK_7BIT ) << 1; + *nBytesWritten = nBytes; + return IVAS_ERR_OK; +} + +static ivas_error unpackReverseISMGain( const uint8_t *buffer, uint32_t numDataBytes, IVAS_PIDATA_GENERIC *piData ) +{ + uint32_t idx; + IVAS_PIDATA_ISM_EDIT_GAIN *r_ism_gain = (IVAS_PIDATA_ISM_EDIT_GAIN *) piData; + + /* R_ISM_GAIN data is 1 byte */ + if ( numDataBytes > 1 ) + { + return IVAS_ERROR( IVAS_ERR_RTP_UNPACK_PI_DATA, "Incorrect size to unpack R_ISM_GAIN PI data" ); + } + + r_ism_gain->size = sizeof( IVAS_PIDATA_ISM_EDIT_GAIN ); + r_ism_gain->piDataType = IVAS_PI_R_ISM_GAIN; + + /* Unpack gain */ + idx = ( *buffer ) >> 1; + /* negative gains*/ + if ( idx < 97 ) + { + r_ism_gain->dB = -(int8_t) ( idx ); + } + /* Set to min for muting, to be interpreted as -Inf */ + else if ( idx == 97 ) + { + r_ism_gain->dB = -128; + } + /* postive gains */ + else if ( idx < 101 ) + { + r_ism_gain->dB = (int8_t) idx - 97; + } + else + { + return IVAS_ERROR( IVAS_ERR_RTP_UNPACK_PI_DATA, "Incorrect index for R_ISM_GAIN PI data" ); + } + + return IVAS_ERR_OK; +} + +static ivas_error packReverseISMDirection( const IVAS_PIDATA_GENERIC *piData, uint8_t *buffer, uint32_t maxDataBytes, uint32_t *nBytesWritten ) +{ + uint32_t nBytes = 0; + const IVAS_PIDATA_ISM_EDIT_DIRECTION *r_ism_direction = (const IVAS_PIDATA_ISM_EDIT_DIRECTION *) piData; + uint16_t word; + + *nBytesWritten = 0; + + if ( piData->size > sizeof( IVAS_PIDATA_ISM_EDIT_DIRECTION ) ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect size in R_ISM_DIRECTION PI data" ); + } + + if ( piData->piDataType != IVAS_PI_R_ISM_DIRECTION ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect PI ID in ISM_DIRECTION PI data" ); + } + + /* R_ISM_DIRECTION data is 2 bytes, header is 2 bytes */ + if ( maxDataBytes > 2 + 2 ) + { + return IVAS_ERROR( IVAS_ERR_RTP_INSUFFICIENT_OUTPUT_SIZE, "Insufficient space to pack R_ISM_DIRECTION PI data" ); + } + + buffer[nBytes++] = ( r_ism_direction->piDataType & MASK_5BIT ); /* PF/PM populated during final packing */ + + word = (uint16_t) ( min( (uint16_t) ceilf( r_ism_direction->azimuth * REVERSE_ISM_DIRECTION_AZIMUTH_STEP_INV ) + 256, 511 ) << 7 ); + word |= (uint16_t) ( min( (uint16_t) ceilf( r_ism_direction->elevation * REVERSE_ISM_DIRECTION_ELEVATION_STEP_INV ) + 64, 127 ) << 6 ); + + buffer[nBytes++] = ( word >> 8 ) & MASK_8BIT; + buffer[nBytes++] = word & MASK_8BIT; + + *nBytesWritten = nBytes; + return IVAS_ERR_OK; +} + +static ivas_error unpackReverseISMDirection( const uint8_t *buffer, uint32_t numDataBytes, IVAS_PIDATA_GENERIC *piData ) +{ + uint16_t word; + IVAS_PIDATA_ISM_EDIT_DIRECTION *r_ism_direction = (IVAS_PIDATA_ISM_EDIT_DIRECTION *) piData; + + /* R_ISM_DIRECTION data is 2 bytes */ + if ( numDataBytes > 2 ) + { + return IVAS_ERROR( IVAS_ERR_RTP_UNPACK_PI_DATA, "Incorrect size to unpack R_ISM_DIRECTION PI data" ); + } + + r_ism_direction->size = sizeof( IVAS_PIDATA_ISM_EDIT_DIRECTION ); + r_ism_direction->piDataType = IVAS_PI_R_ISM_DIRECTION; + + word = ( buffer[0] ) << 8; + word |= ( buffer[1] ); + + r_ism_direction->azimuth = (float) ( ( ( word >> 7 ) & MASK_9BIT ) + 1 ) * REVERSE_ISM_DIRECTION_AZIMUTH_STEP - 180.0f; + r_ism_direction->elevation = (float) ( word & MASK_7BIT ) * REVERSE_ISM_DIRECTION_ELEVATION_STEP - 90.0f; + + return IVAS_ERR_OK; +} +#endif #endif /* RTP_S4_251135_CR26253_0016_REV1 */ @@ -1189,7 +1426,11 @@ static const PACK_PI_FN packPiDataFuntions[IVAS_PI_MAX_ID] = { #ifdef RTP_S4_251135_CR26253_0016_REV1 packOrientation, /* PLAYBACK_DEVICE_ORIENTATION */ packOrientation, /* HEAD_ORIENTATION */ +#ifdef REVERSE_ISM_PI_DATA + packPosition, /* LISTENER_POSITION */ +#else packListenerPosition, /* LISTENER_POSITION */ +#endif packDynamicSuppression, /* DYNAMIC_AUDIO_SUPPRESSION */ packAudioFocusCommon, /* AUDIO_FOCUS_REQUEST */ #else @@ -1200,15 +1441,23 @@ static const PACK_PI_FN packPiDataFuntions[IVAS_PI_MAX_ID] = { packUnsupportedData, /* AUDIO_FOCUS_DIRECTION */ #endif packUnsupportedData, /* PI_LATENCY */ - packUnsupportedData, /* R_ISM_ID */ - packUnsupportedData, /* R_ISM_GAIN */ +#ifdef REVERSE_ISM_PI_DATA + packReverseISMID, /* R_ISM_ID */ + packReverseISMGain, /* R_ISM_GAIN */ +#else +#endif #ifdef RTP_S4_251135_CR26253_0016_REV1 packOrientation, /* R_ISM_ORIENTATION */ #else packUnsupportedData, /* R_ISM_ORIENTATION */ #endif +#ifdef REVERSE_ISM_PI_DATA + packPosition, /* R_ISM_POSITION */ + packReverseISMDirection, /* R_ISM_DIRECTION */ +#else packUnsupportedData, /* R_ISM_POSITION */ packUnsupportedData, /* R_ISM_DIRECTION */ +#endif packUnsupportedData, /* RESERVED27 */ packUnsupportedData, /* RESERVED28 */ packUnsupportedData, /* RESERVED29 */ @@ -1258,7 +1507,11 @@ static const UNPACK_PI_FN unpackPiDataFuntions[IVAS_PI_MAX_ID] = { #ifdef RTP_S4_251135_CR26253_0016_REV1 unpackOrientation, /* PLAYBACK_DEVICE_ORIENTATION */ unpackOrientation, /* HEAD_ORIENTATION */ +#ifdef REVERSE_ISM_PI_DATA + unpackPosition, /* LISTENER_POSITION */ +#else unpackListenerPosition, /* LISTENER_POSITION */ +#endif unpackDynamicSuppression, /* DYNAMIC_AUDIO_SUPPRESSION */ unpackAudioFocusCommon, /* AUDIO_FOCUS_REQUEST */ #else @@ -1269,15 +1522,25 @@ static const UNPACK_PI_FN unpackPiDataFuntions[IVAS_PI_MAX_ID] = { unpackUnsupportedData, /* AUDIO_FOCUS_DIRECTION */ #endif unpackUnsupportedData, /* PI_LATENCY */ +#ifdef REVERSE_ISM_PI_DATA + unpackReverseISMID, /* R_ISM_ID */ + unpackReverseISMGain, /* R_ISM_GAIN */ +#else unpackUnsupportedData, /* R_ISM_ID */ unpackUnsupportedData, /* R_ISM_GAIN */ +#endif #ifdef RTP_S4_251135_CR26253_0016_REV1 unpackOrientation, /* R_ISM_ORIENTATION */ #else unpackUnsupportedData, /* R_ISM_ORIENTATION */ #endif +#ifdef REVERSE_ISM_PI_DATA + unpackPosition, /* R_ISM_POSITION */ + unpackReverseISMDirection, /* R_ISM_DIRECTION */ +#else unpackUnsupportedData, /* R_ISM_POSITION */ unpackUnsupportedData, /* R_ISM_DIRECTION */ +#endif unpackUnsupportedData, /* RESERVED27 */ unpackUnsupportedData, /* RESERVED28 */ unpackUnsupportedData, /* RESERVED29 */ diff --git a/lib_util/ivas_rtp_pi_data.h b/lib_util/ivas_rtp_pi_data.h index 773fdf6a91..bfb44ab9cb 100644 --- a/lib_util/ivas_rtp_pi_data.h +++ b/lib_util/ivas_rtp_pi_data.h @@ -39,6 +39,13 @@ #define IVAS_PI_MAX_DATA_SIZE ( 32 + 2 ) /* max packed PI data bytes + pi header bytes */ +#ifdef REVERSE_ISM_PI_DATA +#define REVERSE_ISM_DIRECTION_AZIMUTH_STEP 0.703125f +#define REVERSE_ISM_DIRECTION_ELEVATION_STEP 1.417322835f +#define REVERSE_ISM_DIRECTION_AZIMUTH_STEP_INV 1.4222222222f +#define REVERSE_ISM_DIRECTION_ELEVATION_STEP_INV 0.7055555556f +#endif + /* IVAS PI Data Types */ typedef enum { @@ -338,6 +345,20 @@ typedef struct IVAS_FLVL flvl; /* audio focus level */ } IVAS_PIDATA_AUDIO_FOCUS; +#ifdef REVERSE_ISM_PI_DATA +/* Position data corresponding to any of the following pi data types :- + * - IVAS_PI_LISTENER_POSITION + * - IVAS_PI_R_ISM_POSITION + * + * piDataType is used to identify the correct pi data type contained here + */ +typedef struct +{ + size_t size; /* sizeof(IVAS_PIDATA_POSITION) */ + uint32_t piDataType; /* one of supported position data types */ + IVAS_COORDINATE position; /* Position data */ +} IVAS_PIDATA_POSITION; +#else /* Listener position */ typedef struct { @@ -345,6 +366,7 @@ typedef struct uint32_t piDataType; /* IVAS_PI_LISTENER_POSITION */ IVAS_COORDINATE position; /* Position of audio objects in ISM(s) */ } IVAS_PIDATA_LISTENER_POSITION; +#endif /* Dynamic Audio Suppression describes receiver’s preference with respect to the * type of audio content that should be enhanced and the amount of suppression to @@ -419,6 +441,7 @@ typedef struct IVAS_QUATERNION orientation; /* orientation editing request for received ISM */ } IVAS_PIDATA_ISM_EDIT_ORIENTATION; +#ifndef REVERSE_ISM_PI_DATA /* Editing request for ISM position */ typedef struct { @@ -426,6 +449,7 @@ typedef struct uint32_t piDataType; /* IVAS_PI_R_ISM_POSITION */ IVAS_COORDINATE position; /* Positional editing request for received ISM */ } IVAS_PIDATA_ISM_EDIT_POSITION; +#endif /* Editing request for ISM direction */ typedef struct @@ -465,14 +489,18 @@ typedef union IVAS_PIDATA_ORIENTATION playbackOrientation; IVAS_PIDATA_ORIENTATION headOrientation; +#ifdef REVERSE_ISM_PI_DATA + IVAS_PIDATA_POSITION listnerPosition; +#else IVAS_PIDATA_LISTENER_POSITION listnerPosition; +#endif IVAS_PIDATA_DYNAMIC_SUPPRESSION dynSuppressionRequest; IVAS_PIDATA_AUDIO_FOCUS focusRequest; IVAS_PIDATA_REVERSE_PI_LATENCY piLatency; IVAS_PIDATA_ISM_EDIT_ID ismEditId; IVAS_PIDATA_ISM_EDIT_GAIN ismEditGain; IVAS_PIDATA_ISM_EDIT_ORIENTATION ismEditOrientation; - IVAS_PIDATA_ISM_EDIT_POSITION ismEditPosition; + IVAS_PIDATA_POSITION ismEditPosition; IVAS_PIDATA_ISM_EDIT_DIRECTION ismEditDirection; #endif /* RTP_S4_251135_CR26253_0016_REV1 */ IVAS_PIDATA_NO_DATA noPiData; diff --git a/tests/rtp/ivasrtp.py b/tests/rtp/ivasrtp.py index 301da07760..d09b2b70cf 100644 --- a/tests/rtp/ivasrtp.py +++ b/tests/rtp/ivasrtp.py @@ -430,6 +430,19 @@ class DIRECTIVITY: class ISM_DIRECTIVITY: directivities: list[DIRECTIVITY] +@dataclass +class R_ISM_ID: + id: int + +@dataclass +class R_ISM_GAIN: + gain: int + +@dataclass +class R_ISM_DIRECTION: + azi: float + elev: float + @dataclass class AUDIO_FOCUS: direction: Optional[ORIENTATION] = None @@ -632,6 +645,11 @@ codedFormats = list(FORMATS) codedSubFormats = list(SUBFORMATS) PiTypeNames = list(PIDATAS) +azimuthStepSize = 0.703125 +elevationStepSize = 1.417322835 +azimuthDirections = [round(x * azimuthStepSize - 180, 3) for x in range(1, 512)] +elevationDirections = [round(x * elevationStepSize - 90, 3) for x in range(0, 127)] + def mapNearestIndex(table: list, val: float) -> int: for idx, entry in enumerate(table): @@ -639,6 +657,17 @@ def mapNearestIndex(table: list, val: float) -> int: return idx return len(table) - 1 +def mapNearestIndexDirectionAzi(table: list, val: float) -> int: + for idx, entry in enumerate(table): + if abs(entry - val) < azimuthStepSize: + return idx + return len(table) - 1 + +def mapNearestIndexDirectionElev(table: list, val: float) -> int: + for idx, entry in enumerate(table): + if abs(entry - val) < elevationStepSize: + return idx + return len(table) - 1 getListIndex = lambda mylist, val: mylist.index(val) if val in mylist else -1 @@ -1080,6 +1109,42 @@ def packISMDirectivity(bitstrm: BitStream, data: any): bitstrm.append(f'uint:5={outer_att_idx}') bitstrm.append(f'uint:1=0') +def unpackReverseISMID(bitstrm: ConstBitStream, piSize: int) -> R_ISM_ID: + assert piSize == 1, "Incorrect PI Data Size for R_ISM_ID" + id = bitstrm.read(8).uint + return R_ISM_ID(id=id) + +def packReverseISMID(bitstrm: BitStream, data: any): + assert type(data) == R_ISM_ID, "Data of type R_ISM_ID is expected" + r_ism_id = cast(R_ISM_ID, data) + bitstrm.append(f'uint:8={r_ism_id.id}') + +def unpackReverseISMGain(bitstrm: ConstBitStream, piSize: int) -> R_ISM_GAIN: + assert piSize == 1, "Incorrect PI Data Size for R_ISM_GAIN" + gain = bitstrm.read(7).uint + return R_ISM_GAIN(gain=gain) + +def packReverseISMGain(bitstrm: BitStream, data: any): + assert type(data) == R_ISM_GAIN, "Data of type R_ISM_GAIN is expected" + r_ism_gain = cast(R_ISM_GAIN, data) + gain_idx = getListIndex(ismGains, r_ism_gain.gain) + bitstrm.append(f'uint:7={gain_idx}') + bitstrm.append(f'uint:1=0') + +def unpackReverseISMDirection(bitstrm: ConstBitStream, piSize: int) -> R_ISM_DIRECTION: + assert piSize == 2, "Incorrect PI Data Size for R_ISM_DIRECTION" + azimuth = bitstrm.read(9).uint + elevation = bitstrm.read(7).uint + return R_ISM_DIRECTION(azi=azimuth, elev=elevation) + +def packReverseISMDirection(bitstrm: BitStream, data: any): + assert type(data) == R_ISM_DIRECTION, "Data of type R_ISM_DIRECTION is expected" + direction = cast(R_ISM_DIRECTION, data) + azimuth_idx = mapNearestIndexDirectionAzi(azimuthDirections, direction.azi) + elevation_idx = mapNearestIndexDirectionElev(elevationDirections, direction.elev) + bitstrm.append(f'uint:9={azimuth_idx}') + bitstrm.append(f'uint:7={elevation_idx}') + PIDataUnpacker = [ unpackOrientation, # SCENE_ORIENTATION, unpackOrientation, # DEVICE_ORIENTATION_COMPENSATED, @@ -1103,11 +1168,11 @@ PIDataUnpacker = [ unpackDAS, # DYNAMIC_AUDIO_SUPPRESSION_REQUEST unpackAudioFocus, # AUDIO_FOCUS_REQUEST unpackUnsupported, # PI_LATENCY - unpackUnsupported, # R_ISM_ID - unpackUnsupported, # R_ISM_GAIN + unpackReverseISMID, # R_ISM_ID + unpackReverseISMGain, # R_ISM_GAIN unpackOrientation, # R_ISM_ORIENTATION unpackPosition, # R_ISM_POSITION - unpackUnsupported, # R_ISM_DIRECTION + unpackReverseISMDirection, # R_ISM_DIRECTION unpackUnsupported, # RESERVED27 unpackUnsupported, # RESERVED28 unpackUnsupported, # RESERVED29 @@ -1138,11 +1203,11 @@ PIDataPacker = [ packDAS, # DYNAMIC_AUDIO_SUPPRESSION_REQUEST packAudioFocus, # AUDIO_FOCUS_DIRECTION packUnsupported, # PI_LATENCY - packUnsupported, # R_ISM_ID - packUnsupported, # R_ISM_GAIN + packReverseISMID, # R_ISM_ID + packReverseISMGain, # R_ISM_GAIN packOrientation, # R_ISM_ORIENTATION packPosition, # R_ISM_POSITION - packUnsupported, # R_ISM_DIRECTION + packReverseISMDirection, # R_ISM_DIRECTION packUnsupported, # RESERVED27 packUnsupported, # RESERVED28 packUnsupported, # RESERVED29 diff --git a/tests/rtp/test_rtp.py b/tests/rtp/test_rtp.py index fbd8a93fdf..bd04c26080 100644 --- a/tests/rtp/test_rtp.py +++ b/tests/rtp/test_rtp.py @@ -236,6 +236,10 @@ def generatePiData(startTs: int, endTs: int) -> dict: someISMDistanceAttenuations = lambda num_ism : [DISTANCE_ATTENUATION(ref_dist=random.randint(1,64)/10.0, max_dist=random.randint(1,64), roll_off=random.randint(0,40)/10.0) for _ in range(num_ism)] someISMDirectivities = lambda num_ism : [DIRECTIVITY(inner_ang=random.randint(0,24)*15, outer_ang=random.randint(0,24)*15, outer_att=random.randint(-30,0)*3) for _ in range(num_ism)] + someReverseISMId = lambda : R_ISM_ID(id=(random.getrandbits(8))) + someReverseISMGain = lambda : R_ISM_GAIN(gain=int(random.randint(-96,3))) + someReverseISMDirection = lambda : R_ISM_DIRECTION( azi=random.randint(1,512) * azimuthStepSize - 180.0, elev=random.randint(0,127) * elevationStepSize - 90.0 ) + for ts in range(startTs, endTs, 320): pidata = dict() pidata["SCENE_ORIENTATION"] = someOrientation() @@ -258,6 +262,12 @@ def generatePiData(startTs: int, endTs: int) -> dict: pidata["ISM_POSITION"] = someISMPositions(pidata["ISM_NUM"].num) pidata["ISM_DISTANCE_ATTENUATION"] = someISMDistanceAttenuations(pidata["ISM_NUM"].num) pidata["ISM_DIRECTIVITY"] = someISMDirectivities(pidata["ISM_NUM"].num) + + pidata["R_ISM_ID"] = someReverseISMId() + pidata["R_ISM_GAIN"] = someReverseISMGain() + pidata["R_ISM_ORIENTATION"] = someOrientation() + pidata["R_ISM_POSITION"] = somePosition() + pidata["R_ISM_DIRECTION"] = someReverseISMDirection() data[str(ts)] = pidata return data @@ -369,6 +379,17 @@ def isEqualISMDirectivity(ref: DIRECTIVITY, dut: DIRECTIVITY): assert ref.outer_ang == dut.outer_ang, "DIRECTIVITY PI Data mismatch in outer_ang" assert abs(ref.outer_att - dut.outer_att) < 0.0001, "DIRECTIVITY PI Data mismatch in outer_att" +def isEqualReverseISMID(ref: R_ISM_ID, dut: R_ISM_ID): + assert ref.id == dut.id, f"Reverse ISM ID PI Data mismatch {ref.id} != {dut.id}" + +def isEqualReverseISMGain(ref: R_ISM_GAIN, dut: R_ISM_GAIN): + assert ref.gain == dut.gain, f"Reverse ISM GAIN PI Data mismatch {ref.gain} != {dut.gain}" + +def isEqualReverseISMDirection(ref: R_ISM_DIRECTION, dut: R_ISM_DIRECTION): + assert abs(ref.azi - dut.azi) < azimuthStepSize + 0.1, "Reverse ISM Direction PI Data mismatch in azimuth (more than one index difference)" + assert abs(ref.elev - dut.elev) < elevationStepSize + 0.1, "Reverse ISM Direction PI Data mismatch in elevation (more than one index difference)" + + class CSVREADER: def __init__(self, csvFile: Path): self.rIdx = 0 @@ -688,7 +709,14 @@ def run_rtp_bitstream_tests( elif type(generatedPIData[ts][pitype]) == ISM_ID: isEqualISMID(ISM_ID(**decoded), data) elif type(generatedPIData[ts][pitype]) == ISM_GAIN: - isEqualISMGain(ISM_GAIN(**decoded), data) + isEqualISMGain(ISM_GAIN(**decoded), data) + elif type(generatedPIData[ts][pitype]) == R_ISM_ID: + isEqualReverseISMID(R_ISM_ID(**decoded), data) + elif type(generatedPIData[ts][pitype]) == R_ISM_GAIN: + isEqualReverseISMGain(R_ISM_GAIN(**decoded), data) + elif type(generatedPIData[ts][pitype]) == R_ISM_DIRECTION: + isEqualReverseISMDirection(R_ISM_DIRECTION(**decoded), data) + else: assert False, "Unsupported PI data found" -- GitLab From 165467230f3cda5b691c7563d2baeb2f568c0175 Mon Sep 17 00:00:00 2001 From: Lauros Pajunen Date: Fri, 7 Nov 2025 12:28:46 +0200 Subject: [PATCH 2/4] Fix flags --- lib_util/ivas_rtp_pi_data.c | 2 ++ lib_util/ivas_rtp_pi_data.h | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/lib_util/ivas_rtp_pi_data.c b/lib_util/ivas_rtp_pi_data.c index 22c1ac2b40..d7cd9b7e83 100644 --- a/lib_util/ivas_rtp_pi_data.c +++ b/lib_util/ivas_rtp_pi_data.c @@ -1445,6 +1445,8 @@ static const PACK_PI_FN packPiDataFuntions[IVAS_PI_MAX_ID] = { packReverseISMID, /* R_ISM_ID */ packReverseISMGain, /* R_ISM_GAIN */ #else + packUnsupportedData, /* R_ISM_ID */ + packUnsupportedData, /* R_ISM_GAIN */ #endif #ifdef RTP_S4_251135_CR26253_0016_REV1 packOrientation, /* R_ISM_ORIENTATION */ diff --git a/lib_util/ivas_rtp_pi_data.h b/lib_util/ivas_rtp_pi_data.h index bfb44ab9cb..006389fbfd 100644 --- a/lib_util/ivas_rtp_pi_data.h +++ b/lib_util/ivas_rtp_pi_data.h @@ -500,7 +500,11 @@ typedef union IVAS_PIDATA_ISM_EDIT_ID ismEditId; IVAS_PIDATA_ISM_EDIT_GAIN ismEditGain; IVAS_PIDATA_ISM_EDIT_ORIENTATION ismEditOrientation; +#ifdef REVERSE_ISM_PI_DATA IVAS_PIDATA_POSITION ismEditPosition; +#else + IVAS_PIDATA_ISM_EDIT_POSITION ismEditPosition; +#endif IVAS_PIDATA_ISM_EDIT_DIRECTION ismEditDirection; #endif /* RTP_S4_251135_CR26253_0016_REV1 */ IVAS_PIDATA_NO_DATA noPiData; -- GitLab From 00730517f5fcdeb5d63083ff72ffab8ab7d298b7 Mon Sep 17 00:00:00 2001 From: Lauros Pajunen Date: Fri, 7 Nov 2025 12:30:09 +0200 Subject: [PATCH 3/4] Remvoe unused values --- lib_util/ivas_rtp_pi_data.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib_util/ivas_rtp_pi_data.c b/lib_util/ivas_rtp_pi_data.c index d7cd9b7e83..ca7eec76f7 100644 --- a/lib_util/ivas_rtp_pi_data.c +++ b/lib_util/ivas_rtp_pi_data.c @@ -1201,7 +1201,7 @@ static ivas_error unpackISMDirectivity( const uint8_t *buffer, uint32_t numDataB #ifdef REVERSE_ISM_PI_DATA static ivas_error packReverseISMID( const IVAS_PIDATA_GENERIC *piData, uint8_t *buffer, uint32_t maxDataBytes, uint32_t *nBytesWritten ) { - uint32_t nBytes = 0, n; + uint32_t nBytes = 0; const IVAS_PIDATA_ISM_EDIT_ID *r_ism_id = (const IVAS_PIDATA_ISM_EDIT_ID *) piData; *nBytesWritten = 0; @@ -1230,7 +1230,6 @@ static ivas_error packReverseISMID( const IVAS_PIDATA_GENERIC *piData, uint8_t * static ivas_error unpackReverseISMID( const uint8_t *buffer, uint32_t numDataBytes, IVAS_PIDATA_GENERIC *piData ) { - uint32_t n; IVAS_PIDATA_ISM_EDIT_ID *r_ism_id = (IVAS_PIDATA_ISM_EDIT_ID *) piData; /* ISM_ID data is 1 byte*/ -- GitLab From df5a71c84ddf10c4834c7e51773d6751abf50fa3 Mon Sep 17 00:00:00 2001 From: Lauros Pajunen Date: Mon, 10 Nov 2025 14:21:54 +0200 Subject: [PATCH 4/4] Clang format --- lib_util/ivas_rtp_pi_data.c | 30 +++++++++++++++--------------- lib_util/ivas_rtp_pi_data.h | 6 +++--- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/lib_util/ivas_rtp_pi_data.c b/lib_util/ivas_rtp_pi_data.c index ca7eec76f7..0993386c21 100644 --- a/lib_util/ivas_rtp_pi_data.c +++ b/lib_util/ivas_rtp_pi_data.c @@ -1423,10 +1423,10 @@ static const PACK_PI_FN packPiDataFuntions[IVAS_PI_MAX_ID] = { #endif packUnsupportedData, /* RESERVED15 */ #ifdef RTP_S4_251135_CR26253_0016_REV1 - packOrientation, /* PLAYBACK_DEVICE_ORIENTATION */ - packOrientation, /* HEAD_ORIENTATION */ + packOrientation, /* PLAYBACK_DEVICE_ORIENTATION */ + packOrientation, /* HEAD_ORIENTATION */ #ifdef REVERSE_ISM_PI_DATA - packPosition, /* LISTENER_POSITION */ + packPosition, /* LISTENER_POSITION */ #else packListenerPosition, /* LISTENER_POSITION */ #endif @@ -1441,11 +1441,11 @@ static const PACK_PI_FN packPiDataFuntions[IVAS_PI_MAX_ID] = { #endif packUnsupportedData, /* PI_LATENCY */ #ifdef REVERSE_ISM_PI_DATA - packReverseISMID, /* R_ISM_ID */ + packReverseISMID, /* R_ISM_ID */ packReverseISMGain, /* R_ISM_GAIN */ #else - packUnsupportedData, /* R_ISM_ID */ - packUnsupportedData, /* R_ISM_GAIN */ + packUnsupportedData, /* R_ISM_ID */ + packUnsupportedData, /* R_ISM_GAIN */ #endif #ifdef RTP_S4_251135_CR26253_0016_REV1 packOrientation, /* R_ISM_ORIENTATION */ @@ -1453,11 +1453,11 @@ static const PACK_PI_FN packPiDataFuntions[IVAS_PI_MAX_ID] = { packUnsupportedData, /* R_ISM_ORIENTATION */ #endif #ifdef REVERSE_ISM_PI_DATA - packPosition, /* R_ISM_POSITION */ + packPosition, /* R_ISM_POSITION */ packReverseISMDirection, /* R_ISM_DIRECTION */ #else - packUnsupportedData, /* R_ISM_POSITION */ - packUnsupportedData, /* R_ISM_DIRECTION */ + packUnsupportedData, /* R_ISM_POSITION */ + packUnsupportedData, /* R_ISM_DIRECTION */ #endif packUnsupportedData, /* RESERVED27 */ packUnsupportedData, /* RESERVED28 */ @@ -1506,12 +1506,12 @@ static const UNPACK_PI_FN unpackPiDataFuntions[IVAS_PI_MAX_ID] = { #endif unpackUnsupportedData, /* RESERVED15 */ #ifdef RTP_S4_251135_CR26253_0016_REV1 - unpackOrientation, /* PLAYBACK_DEVICE_ORIENTATION */ - unpackOrientation, /* HEAD_ORIENTATION */ + unpackOrientation, /* PLAYBACK_DEVICE_ORIENTATION */ + unpackOrientation, /* HEAD_ORIENTATION */ #ifdef REVERSE_ISM_PI_DATA - unpackPosition, /* LISTENER_POSITION */ + unpackPosition, /* LISTENER_POSITION */ #else - unpackListenerPosition, /* LISTENER_POSITION */ + unpackListenerPosition, /* LISTENER_POSITION */ #endif unpackDynamicSuppression, /* DYNAMIC_AUDIO_SUPPRESSION */ unpackAudioFocusCommon, /* AUDIO_FOCUS_REQUEST */ @@ -1524,7 +1524,7 @@ static const UNPACK_PI_FN unpackPiDataFuntions[IVAS_PI_MAX_ID] = { #endif unpackUnsupportedData, /* PI_LATENCY */ #ifdef REVERSE_ISM_PI_DATA - unpackReverseISMID, /* R_ISM_ID */ + unpackReverseISMID, /* R_ISM_ID */ unpackReverseISMGain, /* R_ISM_GAIN */ #else unpackUnsupportedData, /* R_ISM_ID */ @@ -1536,7 +1536,7 @@ static const UNPACK_PI_FN unpackPiDataFuntions[IVAS_PI_MAX_ID] = { unpackUnsupportedData, /* R_ISM_ORIENTATION */ #endif #ifdef REVERSE_ISM_PI_DATA - unpackPosition, /* R_ISM_POSITION */ + unpackPosition, /* R_ISM_POSITION */ unpackReverseISMDirection, /* R_ISM_DIRECTION */ #else unpackUnsupportedData, /* R_ISM_POSITION */ diff --git a/lib_util/ivas_rtp_pi_data.h b/lib_util/ivas_rtp_pi_data.h index 2225da32a5..d3d8487e8e 100644 --- a/lib_util/ivas_rtp_pi_data.h +++ b/lib_util/ivas_rtp_pi_data.h @@ -40,9 +40,9 @@ #define IVAS_PI_MAX_DATA_SIZE ( 32 + 2 ) /* max packed PI data bytes + pi header bytes */ #ifdef REVERSE_ISM_PI_DATA -#define REVERSE_ISM_DIRECTION_AZIMUTH_STEP 0.703125f -#define REVERSE_ISM_DIRECTION_ELEVATION_STEP 1.417322835f -#define REVERSE_ISM_DIRECTION_AZIMUTH_STEP_INV 1.4222222222f +#define REVERSE_ISM_DIRECTION_AZIMUTH_STEP 0.703125f +#define REVERSE_ISM_DIRECTION_ELEVATION_STEP 1.417322835f +#define REVERSE_ISM_DIRECTION_AZIMUTH_STEP_INV 1.4222222222f #define REVERSE_ISM_DIRECTION_ELEVATION_STEP_INV 0.7055555556f #endif -- GitLab