From c1dc8a1cf7aec74944ddadaa141bb0ff54d47940 Mon Sep 17 00:00:00 2001 From: Lauros Pajunen Date: Tue, 18 Nov 2025 22:59:34 -0600 Subject: [PATCH 01/24] Implement changes according to new spec - 5 bits for PI size - Only 1 byte per orientation component - Add compact positions for ISM and reverse ISM PI --- lib_com/options.h | 1 + lib_util/ivas_rtp_file.c | 64 +++++- lib_util/ivas_rtp_internal.h | 11 ++ lib_util/ivas_rtp_payload.c | 12 ++ lib_util/ivas_rtp_pi_data.c | 367 +++++++++++++++++++++++++++++++++++ lib_util/ivas_rtp_pi_data.h | 12 ++ tests/rtp/ivasrtp.py | 81 ++++++-- 7 files changed, 523 insertions(+), 25 deletions(-) diff --git a/lib_com/options.h b/lib_com/options.h index 7aa9f1c915..2d39346da6 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -169,6 +169,7 @@ #define DECODER_FORMAT_SWITCHING /* Re-initialize the decoder when the format/subformat of the incoming stream is changed */ #define RTP_SR_CODEC_FRAME_SIZE_IN_TOC_BYTE /* CR for split rendering codec framesize signalling in Toc Byte*/ #define FIX_SPLIT_RENDERING_ON_DECODER_RESTART /* Re-configure split rendering on decoder restart */ +#define RTP_UPDATES_SA4_134 /* Updates to RTP during SA4 134 */ /* ################### 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 b8e79fad53..009a158c49 100644 --- a/lib_util/ivas_rtp_file.c +++ b/lib_util/ivas_rtp_file.c @@ -144,11 +144,10 @@ static ivas_error IvasRtpFile_Read( static const char *const PiDataNames[IVAS_PI_MAX_ID] = { "SCENE_ORIENTATION", "DEVICE_ORIENTATION_COMPENSATED", "DEVICE_ORIENTATION_UNCOMPENSATED", "ACOUSTIC_ENVIRONMENT", "AUDIO_DESCRIPTION", "ISM_NUM", "ISM_ID", "ISM_GAIN", "ISM_ORIENTATION", - "ISM_POSITION", "ISM_DISTANCE_ATTENUATION", "ISM_DIRECTIVITY", "DIEGETIC_TYPE", "DYNAMIC_AUDIO_SUPPRESSION_INDICATION", - "AUDIO_FOCUS_INDICATION", "RESERVED15", "PLAYBACK_DEVICE_ORIENTATION", "HEAD_ORIENTATION", "LISTENER_POSITION", + "ISM_POSITION", "ISM_POSITION_COMPACT", "ISM_DISTANCE_ATTENUATION", "ISM_DIRECTIVITY", "DIEGETIC_TYPE", "DYNAMIC_AUDIO_SUPPRESSION_INDICATION", + "AUDIO_FOCUS_INDICATION", "PLAYBACK_DEVICE_ORIENTATION", "HEAD_ORIENTATION", "LISTENER_POSITION", "DYNAMIC_AUDIO_SUPPRESSION_REQUEST", "AUDIO_FOCUS_REQUEST", "PI_LATENCY", "R_ISM_ID", "R_ISM_GAIN", - "R_ISM_ORIENTATION", "R_ISM_POSITION", "R_ISM_DIRECTION", "RESERVED27", "RESERVED28", "RESERVED29", - "RESERVED30", "NO_DATA" + "R_ISM_ORIENTATION", "R_ISM_POSITION", "R_ISM_POSITION_COMPACT", "R_ISM_DIRECTION", "RESERVED27", "RESERVED28", "RESERVED29", "NO_DATA" }; void IVAS_RTP_LogPiData( @@ -335,11 +334,17 @@ void IVAS_RTP_LogPiData( fprintf( f_piDataOut, "\n\t\t}" ); } break; +#ifdef RTP_S4_251135_CR26253_0016_REV1 + case IVAS_PI_RESERVED27: + case IVAS_PI_RESERVED28: + case IVAS_PI_RESERVED29: +#else case IVAS_PI_RESERVED15: case IVAS_PI_RESERVED27: case IVAS_PI_RESERVED28: case IVAS_PI_RESERVED29: case IVAS_PI_RESERVED30: +#endif { fprintf( f_piDataOut, "{}" ); } @@ -413,6 +418,22 @@ void IVAS_RTP_LogPiData( fprintf( f_piDataOut, "\n\t\t]" ); } break; +#ifdef RTP_UPDATES_SA4_134 + case IVAS_PI_ISM_POSITION_COMPACT: + { + fprintf( f_piDataOut, "[\n" ); + for ( n = 0; n < cur->data.ismPositionCompact.numObjects; n++ ) + { + if ( n != 0 ) + { + fprintf( f_piDataOut, ",\n" ); + } + fprintf( f_piDataOut, "\t\t\t{\n\t\t\t\t\"x\": %f,\n\t\t\t\t\"y\": %f,\n\t\t\t\t\"z\": %f \n\t\t\t}", cur->data.ismPositionCompact.position[n].x, cur->data.ismPositionCompact.position[n].y, cur->data.ismPositionCompact.position[n].z ); + } + fprintf( f_piDataOut, "\n\t\t]" ); + } + break; +#endif case IVAS_PI_ISM_DISTANCE_ATTENUATION: { fprintf( f_piDataOut, "[\n" ); @@ -491,6 +512,14 @@ void IVAS_RTP_LogPiData( cur->data.ismEditPosition.position.x, cur->data.ismEditPosition.position.y, cur->data.ismEditPosition.position.z ); } break; +#ifdef RTP_UPDATES_SA4_134 + case IVAS_PI_R_ISM_POSITION_COMPACT: + { + 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.ismEditPositionCompact.position.x, cur->data.ismEditPositionCompact.position.y, cur->data.ismEditPositionCompact.position.z ); + } + break; +#endif #endif case IVAS_PI_R_ISM_DIRECTION: #ifdef REVERSE_ISM_PI_DATA @@ -631,6 +660,20 @@ void IVAS_RTP_WriteExtPiData( } } break; +#ifdef RTP_UPDATES_SA4_134 + case IVAS_PI_ISM_POSITION_COMPACT: + { + for ( i = 0; i < numObj; ++i ) + { + if ( i != 0 ) + { + fprintf( f_piDataOut, "," ); + } + fprintf( f_piDataOut, "%f,%f,%f", cur->data.ismPositionCompact.position[i].x, cur->data.ismPositionCompact.position[i].y, cur->data.ismPositionCompact.position[i].z ); + } + } + break; +#endif case IVAS_PI_ISM_DISTANCE_ATTENUATION: { for ( i = 0; i < numObj; ++i ) @@ -746,16 +789,29 @@ void IVAS_RTP_WriteExtPiData( fprintf( f_piDataOut, "%f,%f,%f", cur->data.ismEditPosition.position.x, cur->data.ismEditPosition.position.y, cur->data.ismEditPosition.position.z ); } break; +#ifdef RTP_UPDATES_SA4_134 + case IVAS_PI_R_ISM_POSITION_COMPACT: + { + fprintf( f_piDataOut, "%f,%f,%f", cur->data.ismEditPositionCompact.position.x, cur->data.ismEditPositionCompact.position.y, cur->data.ismEditPositionCompact.position.z ); + } + break; +#endif case IVAS_PI_R_ISM_DIRECTION: { fprintf( f_piDataOut, "%f,%f", cur->data.ismEditDirection.azimuth, cur->data.ismEditDirection.elevation ); } break; +#ifdef RTP_UPDATES_SA4_134 + case IVAS_PI_RESERVED27: + case IVAS_PI_RESERVED28: + case IVAS_PI_RESERVED29: +#else case IVAS_PI_RESERVED15: case IVAS_PI_RESERVED27: case IVAS_PI_RESERVED28: case IVAS_PI_RESERVED29: case IVAS_PI_RESERVED30: +#endif break; #endif /* RTP_S4_251135_CR26253_0016_REV1 */ } diff --git a/lib_util/ivas_rtp_internal.h b/lib_util/ivas_rtp_internal.h index a550892548..78f416879f 100644 --- a/lib_util/ivas_rtp_internal.h +++ b/lib_util/ivas_rtp_internal.h @@ -51,6 +51,10 @@ enum MASK_BITS #ifdef REVERSE_ISM_PI_DATA MASK_9BIT = 0x1FF, #endif +#ifdef RTP_UPDATES_SA4_134 + MASK_10BIT = 0x2FF, + MASK_11BIT = 0x3FF, +#endif }; @@ -69,6 +73,13 @@ enum MASK_BITS #define MAX_PI_POSITION_METERS ( 327.68f ) #define FLOAT_FROM_Q15( q15Val ) ( (float) ( q15Val ) / 32768.0f ) +#ifdef RTP_UPDATES_SA4_134 +#define MAX_PI_COMPACT_POSITION_XY_METERS ( 10.24f ) +#define MAX_PI_COMPACT_POSITION_Z_METERS ( 5.12f ) +#define FLOAT_FROM_Q11( q11Val ) ( (float) ( q11Val ) / 2048.0f ) +#define FLOAT_FROM_Q10( q10Val ) ( (float) ( q10Val ) / 1024.0f ) +#define FLOAT_FROM_Q7( q7Val ) ( (float) ( q7Val ) / 128.0f ) +#endif extern const float mapDSR[1u << NBITS_DSR]; extern const float mapRT60[1u << NBITS_RT60]; diff --git a/lib_util/ivas_rtp_payload.c b/lib_util/ivas_rtp_payload.c index 0398d9ce40..ce529094f0 100644 --- a/lib_util/ivas_rtp_payload.c +++ b/lib_util/ivas_rtp_payload.c @@ -1585,6 +1585,17 @@ static ivas_error parsePIData( IVAS_RTP_UNPACK_HANDLE hUnpack, uint32_t rtpTimes PM = ( piHeader0 & ( ~MASK_5BIT ) ) & MASK_7BIT; /* PI Marker Bits */ piDataType = ( piHeader0 & MASK_5BIT ); +#ifdef RTP_UPDATES_SA4_134 + do + { + byte = payload->buffer[nBytes++]; + piSize += ( byte & MASK_5BIT ); + if ( nBytes >= payload->length ) + { + return IVAS_ERROR( IVAS_ERR_RTP_UNDERFLOW, "Underflow during reading piSize" ); + } + } while ( byte == 32 ); +#else do { byte = payload->buffer[nBytes++]; @@ -1594,6 +1605,7 @@ static ivas_error parsePIData( IVAS_RTP_UNPACK_HANDLE hUnpack, uint32_t rtpTimes return IVAS_ERROR( IVAS_ERR_RTP_UNDERFLOW, "Underflow during reading piSize" ); } } while ( byte == 255 ); +#endif if ( piDataType == IVAS_PI_NO_DATA ) { diff --git a/lib_util/ivas_rtp_pi_data.c b/lib_util/ivas_rtp_pi_data.c index b9b7bcc7e4..e8a7d05304 100644 --- a/lib_util/ivas_rtp_pi_data.c +++ b/lib_util/ivas_rtp_pi_data.c @@ -79,6 +79,47 @@ static int16_t ivasPayload_convertToQ15( float value ) return (int16_t) ( value ); } +#ifdef RTP_UPDATES_SA4_134 +/*-----------------------------------------------------------------------* + * ivasPayload_convertToQ11() + * + * Convert a float value into a Q11 encoded value. + *-----------------------------------------------------------------------*/ +static int16_t ivasPayload_convertToQ11( float value ) +{ + value = ( value * 2048.0f ); + value = value > +2048.0f ? +2048.0f : value; + value = value < -2048.0f ? -2048.0f : value; + return (int16_t) ( value ); +} + +/*-----------------------------------------------------------------------* + * ivasPayload_convertToQ10() + * + * Convert a float value into a Q10 encoded value. + *-----------------------------------------------------------------------*/ +static int16_t ivasPayload_convertToQ10( float value ) +{ + value = ( value * 1024.0f ); + value = value > +1024.0f ? +1024.0f : value; + value = value < -1024.0f ? -1024.0f : value; + return (int16_t) ( value ); +} + +/*-----------------------------------------------------------------------* + * ivasPayload_convertToQ7() + * + * Convert a float value into a Q7 encoded value. + *-----------------------------------------------------------------------*/ +static int16_t ivasPayload_convertToQ7( float value ) +{ + value = ( value * 128.0f ); + value = value > +128.0f ? +128.0f : value; + value = value < -128.0f ? -128.0f : value; + return (int16_t) ( value ); +} +#endif + static ivas_error packUnsupportedData( const IVAS_PIDATA_GENERIC *piData, uint8_t *buffer, uint32_t maxDataBytes, uint32_t *nBytesWritten ) { (void) piData; @@ -152,18 +193,34 @@ static ivas_error packOrientation( const IVAS_PIDATA_GENERIC *piData, uint8_t *b return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect PI ID in Orientation PI data" ); } +#ifdef RTP_UPDATES_SA4_134 + /* Orientation data is 4 bytes, header is 2 bytes */ + if ( maxDataBytes < 4 + 2 ) + { + return IVAS_ERROR( IVAS_ERR_RTP_INSUFFICIENT_OUTPUT_SIZE, "Insufficient space to pack Orientation PI data" ); + } +#else /* Orientation data is 8 bytes, header is 2 bytes */ if ( maxDataBytes < 8 + 2 ) { return IVAS_ERROR( IVAS_ERR_RTP_INSUFFICIENT_OUTPUT_SIZE, "Insufficient space to pack Orientation PI data" ); } +#endif buffer[nBytes++] = ( orientation->piDataType & MASK_5BIT ); /* PF/PM populated during final packing */ +#ifdef RTP_UPDATES_SA4_134 + buffer[nBytes++] = 4; + buffer[nBytes++] = (uint8_t) ivasPayload_convertToQ7( orientation->orientation.w ); + buffer[nBytes++] = (uint8_t) ivasPayload_convertToQ7( orientation->orientation.x ); + buffer[nBytes++] = (uint8_t) ivasPayload_convertToQ7( orientation->orientation.y ); + buffer[nBytes++] = (uint8_t) ivasPayload_convertToQ7( orientation->orientation.z ); +#else buffer[nBytes++] = 8; nBytes = writeInt16( buffer, nBytes, ivasPayload_convertToQ15( orientation->orientation.w ) ); nBytes = writeInt16( buffer, nBytes, ivasPayload_convertToQ15( orientation->orientation.x ) ); nBytes = writeInt16( buffer, nBytes, ivasPayload_convertToQ15( orientation->orientation.y ) ); nBytes = writeInt16( buffer, nBytes, ivasPayload_convertToQ15( orientation->orientation.z ) ); +#endif *nBytesWritten = nBytes; return IVAS_ERR_OK; @@ -186,13 +243,31 @@ static ivas_error packISMOrientation( const IVAS_PIDATA_GENERIC *piData, uint8_t { return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect PI ID in Orientation PI data" ); } +#ifdef RTP_UPDATES_SA4_134 + /* Orientation data is 4 bytes, header is 2 bytes */ + if ( maxDataBytes < 4 * IVAS_MAX_NUM_OBJECTS + 2 ) + { + return IVAS_ERROR( IVAS_ERR_RTP_INSUFFICIENT_OUTPUT_SIZE, "Insufficient space to pack Orientation PI data" ); + } +#else /* Orientation data is 8 bytes, header is 2 bytes */ if ( maxDataBytes < 8 * IVAS_MAX_NUM_OBJECTS + 2 ) { return IVAS_ERROR( IVAS_ERR_RTP_INSUFFICIENT_OUTPUT_SIZE, "Insufficient space to pack Orientation PI data" ); } +#endif buffer[nBytes++] = ( orientation->piDataType & MASK_5BIT ); /* PF/PM populated during final packing */ +#ifdef RTP_UPDATES_SA4_134 + buffer[nBytes++] = (uint8_t) orientation->numObjects * 4; + for ( n = 0; n < orientation->numObjects; n++ ) + { + buffer[nBytes++] = (uint8_t) ivasPayload_convertToQ7( orientation->orientation[n].w ); + buffer[nBytes++] = (uint8_t) ivasPayload_convertToQ7( orientation->orientation[n].x ); + buffer[nBytes++] = (uint8_t) ivasPayload_convertToQ7( orientation->orientation[n].y ); + buffer[nBytes++] = (uint8_t) ivasPayload_convertToQ7( orientation->orientation[n].z ); + } +#else buffer[nBytes++] = (uint8_t) orientation->numObjects * 8; for ( n = 0; n < orientation->numObjects; n++ ) { @@ -201,6 +276,7 @@ static ivas_error packISMOrientation( const IVAS_PIDATA_GENERIC *piData, uint8_t nBytes = writeInt16( buffer, nBytes, ivasPayload_convertToQ15( orientation->orientation[n].y ) ); nBytes = writeInt16( buffer, nBytes, ivasPayload_convertToQ15( orientation->orientation[n].z ) ); } +#endif *nBytesWritten = nBytes; return IVAS_ERR_OK; } @@ -210,6 +286,19 @@ static ivas_error unpackOrientation( const uint8_t *buffer, uint32_t numDataByte { IVAS_PIDATA_ORIENTATION *orientation = (IVAS_PIDATA_ORIENTATION *) piData; +#ifdef RTP_UPDATES_SA4_134 + /* Orientation data is 4 bytes */ + if ( numDataBytes != 4 ) + { + return IVAS_ERROR( IVAS_ERR_RTP_UNPACK_PI_DATA, "Incorrect size to unpack Orientation PI data" ); + } + + piData->size = sizeof( IVAS_PIDATA_ORIENTATION ); + orientation->orientation.w = FLOAT_FROM_Q7( buffer[0] ); + orientation->orientation.x = FLOAT_FROM_Q7( buffer[1] ); + orientation->orientation.y = FLOAT_FROM_Q7( buffer[2] ); + orientation->orientation.z = FLOAT_FROM_Q7( buffer[3] ); +#else /* Orientation data is 8 bytes */ if ( numDataBytes != 8 ) { @@ -221,6 +310,7 @@ static ivas_error unpackOrientation( const uint8_t *buffer, uint32_t numDataByte orientation->orientation.x = FLOAT_FROM_Q15( readInt16( &buffer[2] ) ); orientation->orientation.y = FLOAT_FROM_Q15( readInt16( &buffer[4] ) ); orientation->orientation.z = FLOAT_FROM_Q15( readInt16( &buffer[6] ) ); +#endif return IVAS_ERR_OK; } @@ -230,6 +320,25 @@ static ivas_error unpackISMOrientation( const uint8_t *buffer, uint32_t numDataB { IVAS_PIDATA_ISM_ORIENTATION *ism_orientation = (IVAS_PIDATA_ISM_ORIENTATION *) piData; +#ifdef RTP_UPDATES_SA4_134 + /* Orientation data is 4 bytes */ + uint16_t n; + if ( numDataBytes % 4 != 0 ) + { + return IVAS_ERROR( IVAS_ERR_RTP_UNPACK_PI_DATA, "Incorrect size to unpack Orientation PI data" ); + } + + ism_orientation->size = sizeof( IVAS_PIDATA_ISM_ORIENTATION ); + ism_orientation->numObjects = (uint16_t) numDataBytes / 4; + + for ( n = 0; n < ism_orientation->numObjects; n++ ) + { + ism_orientation->orientation[n].w = FLOAT_FROM_Q7( buffer[4 * n] ); + ism_orientation->orientation[n].x = FLOAT_FROM_Q7( buffer[4 * n + 1] ); + ism_orientation->orientation[n].y = FLOAT_FROM_Q7( buffer[4 * n + 2] ); + ism_orientation->orientation[n].z = FLOAT_FROM_Q7( buffer[4 * n + 3] ); + } +#else /* Orientation data is 8 bytes */ uint16_t n; if ( numDataBytes % 8 != 0 ) @@ -247,6 +356,7 @@ static ivas_error unpackISMOrientation( const uint8_t *buffer, uint32_t numDataB ism_orientation->orientation[n].y = FLOAT_FROM_Q15( readInt16( &buffer[8 * n + 4] ) ); ism_orientation->orientation[n].z = FLOAT_FROM_Q15( readInt16( &buffer[8 * n + 6] ) ); } +#endif for ( ; n < IVAS_MAX_NUM_OBJECTS; n++ ) { ism_orientation->orientation[n].w = 0.0f; @@ -614,6 +724,68 @@ static ivas_error unpackListenerPosition( const uint8_t *buffer, uint32_t numDat } #endif +#ifdef RTP_UPDATES_SA4_134 +static ivas_error packPositionCompact( const IVAS_PIDATA_GENERIC *piData, uint8_t *buffer, uint32_t maxDataBytes, uint32_t *nBytesWritten ) +{ + uint32_t nBytes = 0; + uint16_t posX, posY, posZ = 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 compact position PI data" ); + } + + if ( piData->piDataType != IVAS_PI_R_ISM_POSITION ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect PI ID in compact position PI data" ); + } + + /* Compact position data is 4 bytes, header is 2 bytes */ + if ( maxDataBytes < 4 + 2 ) + { + return IVAS_ERROR( IVAS_ERR_RTP_INSUFFICIENT_OUTPUT_SIZE, "Insufficient space to pack compact position PI data" ); + } + + buffer[nBytes++] = ( position->piDataType & MASK_5BIT ); /* PF/PM populated during final packing */ + buffer[nBytes++] = 4; + posX = (uint16_t) ivasPayload_convertToQ11( position->position.x / MAX_PI_COMPACT_POSITION_XY_METERS ); + posY = (uint16_t) ivasPayload_convertToQ11( position->position.y / MAX_PI_COMPACT_POSITION_XY_METERS ); + posZ = (uint16_t) ivasPayload_convertToQ10( position->position.z / MAX_PI_COMPACT_POSITION_Z_METERS ); + buffer[nBytes++] = (uint8_t) ( posX >> 8 ); + buffer[nBytes++] = (uint8_t) ( ( ( posX & MASK_3BIT ) << 5 ) | posY >> 6 ); + buffer[nBytes++] = (uint8_t) ( ( ( posY & MASK_6BIT ) << 2 ) | posZ >> 8 ); + buffer[nBytes++] = (uint8_t) ( posZ >> 2 ); + + *nBytesWritten = nBytes; + + return IVAS_ERR_OK; +} + +static ivas_error unpackPositionCompact( const uint8_t *buffer, uint32_t numDataBytes, IVAS_PIDATA_GENERIC *piData ) +{ + IVAS_PIDATA_POSITION *position = (IVAS_PIDATA_POSITION *) piData; + uint32_t compactRead = 0; + + /* Compact position data is 4 bytes */ + if ( numDataBytes != 4 ) + { + return IVAS_ERROR( IVAS_ERR_RTP_UNPACK_PI_DATA, "Incorrect size to unpack compact position PI data" ); + } + + position->size = sizeof( IVAS_PIDATA_POSITION ); + + compactRead = ( (uint32_t) buffer[0] << 24 ) | ( (uint32_t) buffer[1] << 16 ) | ( (uint32_t) buffer[2] << 8 ) | ( (uint32_t) buffer[3] ); + position->position.x = FLOAT_FROM_Q11( compactRead >> 21 ) * MAX_PI_COMPACT_POSITION_XY_METERS; + position->position.y = FLOAT_FROM_Q11( ( compactRead >> 10 ) & MASK_11BIT ) * MAX_PI_COMPACT_POSITION_XY_METERS; + position->position.z = FLOAT_FROM_Q10( compactRead & MASK_10BIT ) * MAX_PI_COMPACT_POSITION_Z_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 ) { @@ -675,6 +847,74 @@ static ivas_error unpackISMPosition( const uint8_t *buffer, uint32_t numDataByte } #endif +#ifdef RTP_UPDATES_SA4_134 +static ivas_error packISMPositionCompact( const IVAS_PIDATA_GENERIC *piData, uint8_t *buffer, uint32_t maxDataBytes, uint32_t *nBytesWritten ) +{ + uint32_t nBytes = 0, n; + uint16_t posX, posY, posZ = 0; + const IVAS_PIDATA_ISM_POSITION *ism_position = (const IVAS_PIDATA_ISM_POSITION *) piData; + + *nBytesWritten = 0; + + if ( piData->size != sizeof( IVAS_PIDATA_ISM_POSITION ) ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect size in ISM POSITION COMPACT PI data" ); + } + + if ( piData->piDataType != IVAS_PI_ISM_POSITION_COMPACT ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect PI ID in ISM POSITION COMPACT PI data" ); + } + + /* Compact position data is 4 bytes, header is 2 bytes */ + if ( maxDataBytes < 4 * IVAS_MAX_NUM_OBJECTS + 2 ) + { + return IVAS_ERROR( IVAS_ERR_RTP_INSUFFICIENT_OUTPUT_SIZE, "Insufficient space to pack ISM POSITION COMPACT PI data" ); + } + + buffer[nBytes++] = ( ism_position->piDataType & MASK_5BIT ); /* PF/PM populated during final packing */ + buffer[nBytes++] = (uint8_t) ism_position->numObjects * 4; + for ( n = 0; n < ism_position->numObjects; n++ ) + { + posX = (uint16_t) ivasPayload_convertToQ11( ism_position->position[n].x / MAX_PI_COMPACT_POSITION_XY_METERS ); + posY = (uint16_t) ivasPayload_convertToQ11( ism_position->position[n].y / MAX_PI_COMPACT_POSITION_XY_METERS ); + posZ = (uint16_t) ivasPayload_convertToQ10( ism_position->position[n].z / MAX_PI_COMPACT_POSITION_Z_METERS ); + buffer[nBytes++] = (uint8_t) ( posX >> 8 ); + buffer[nBytes++] = (uint8_t) ( ( ( posX & MASK_3BIT ) << 5 ) | posY >> 6 ); + buffer[nBytes++] = (uint8_t) ( ( ( posY & MASK_6BIT ) << 2 ) | posZ >> 8 ); + buffer[nBytes++] = (uint8_t) ( posZ >> 2 ); + } + *nBytesWritten = nBytes; + return IVAS_ERR_OK; +} + +static ivas_error unpackISMPositionCompact( const uint8_t *buffer, uint32_t numDataBytes, IVAS_PIDATA_GENERIC *piData ) +{ + uint16_t n; + uint32_t compactRead = 0; + IVAS_PIDATA_ISM_POSITION *ism_position = (IVAS_PIDATA_ISM_POSITION *) piData; + + /* Compact position data is 4 bytes */ + if ( numDataBytes % 4 != 0 ) + { + return IVAS_ERROR( IVAS_ERR_RTP_UNPACK_PI_DATA, "Incorrect size to unpack ISM POSITION COMPACT PI data" ); + } + + ism_position->size = sizeof( IVAS_PIDATA_ISM_POSITION ); + ism_position->piDataType = IVAS_PI_ISM_POSITION; + ism_position->numObjects = (uint16_t) numDataBytes / 4; + + for ( n = 0; n < ism_position->numObjects; n++ ) + { + compactRead = ( (uint32_t) buffer[0] << 24 ) | ( (uint32_t) buffer[1] << 16 ) | ( (uint32_t) buffer[2] << 8 ) | ( (uint32_t) buffer[3] ); + ism_position->position[n].x = FLOAT_FROM_Q11( compactRead >> 21 ) * MAX_PI_COMPACT_POSITION_XY_METERS; + ism_position->position[n].y = FLOAT_FROM_Q11( ( compactRead >> 10 ) & MASK_11BIT ) * MAX_PI_COMPACT_POSITION_XY_METERS; + ism_position->position[n].z = FLOAT_FROM_Q10( compactRead & MASK_10BIT ) * MAX_PI_COMPACT_POSITION_Z_METERS; + } + return IVAS_ERR_OK; +} +#endif + static ivas_error packDiegetic( const IVAS_PIDATA_GENERIC *piData, uint8_t *buffer, uint32_t maxDataBytes, uint32_t *nBytesWritten ) { uint32_t nBytes = 0, n; @@ -752,6 +992,16 @@ static ivas_error packAudioFocusCommon( const IVAS_PIDATA_GENERIC *piData, uint8 return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect size in PI data of type Audio Focus" ); } +#ifdef RTP_UPDATES_SA4_134 + if ( audioFocus->availDirection && audioFocus->availLevel ) + { + packedSize = 5; + } + else if ( audioFocus->availDirection ) + { + packedSize = 4; + } +#else if ( audioFocus->availDirection && audioFocus->availLevel ) { packedSize = 9; @@ -760,6 +1010,7 @@ static ivas_error packAudioFocusCommon( const IVAS_PIDATA_GENERIC *piData, uint8 { packedSize = 8; } +#endif else if ( audioFocus->availLevel ) { packedSize = 1; @@ -778,6 +1029,19 @@ static ivas_error packAudioFocusCommon( const IVAS_PIDATA_GENERIC *piData, uint8 buffer[nBytes++] = ( audioFocus->piDataType & MASK_5BIT ); /* PF/PM populated during final packing */ buffer[nBytes++] = packedSize; +#ifdef RTP_UPDATES_SA4_134 + if ( packedSize == 5 || packedSize == 4 ) + { + buffer[nBytes++] = (uint8_t) ivasPayload_convertToQ7( audioFocus->direction.w ); + buffer[nBytes++] = (uint8_t) ivasPayload_convertToQ7( audioFocus->direction.x ); + buffer[nBytes++] = (uint8_t) ivasPayload_convertToQ7( audioFocus->direction.y ); + buffer[nBytes++] = (uint8_t) ivasPayload_convertToQ7( audioFocus->direction.z ); + } + if ( packedSize == 5 || packedSize == 1 ) + { + buffer[nBytes++] = ( (uint8_t) audioFocus->flvl & MASK_4BIT ) << 4; + } +#else if ( packedSize == 9 || packedSize == 8 ) { nBytes = writeInt16( buffer, nBytes, ivasPayload_convertToQ15( audioFocus->direction.w ) ); @@ -789,6 +1053,7 @@ static ivas_error packAudioFocusCommon( const IVAS_PIDATA_GENERIC *piData, uint8 { buffer[nBytes++] = ( (uint8_t) audioFocus->flvl & MASK_4BIT ) << 4; } +#endif *nBytesWritten = nBytes; return IVAS_ERR_OK; @@ -798,6 +1063,34 @@ static ivas_error unpackAudioFocusCommon( const uint8_t *buffer, uint32_t numDat { IVAS_PIDATA_AUDIO_FOCUS *audioFocus = (IVAS_PIDATA_AUDIO_FOCUS *) piData; +#ifdef RTP_UPDATES_SA4_134 + /* Audio Focus data is either 1, 4 or 5 bytes */ + if ( numDataBytes != 1 && numDataBytes != 4 && numDataBytes != 5 ) + { + return IVAS_ERROR( IVAS_ERR_RTP_UNPACK_PI_DATA, "Incorrect size to unpack PI data of type Audio Focus" ); + } + + piData->size = sizeof( IVAS_PIDATA_AUDIO_FOCUS ); + audioFocus->availDirection = ( numDataBytes >= 4 ); + audioFocus->availLevel = ( numDataBytes == 1 || numDataBytes == 5 ); + + if ( numDataBytes == 1 ) + { + audioFocus->flvl = ( buffer[0] >> 4 ); + } + else + { + audioFocus->direction.w = FLOAT_FROM_Q7( buffer[0] ); + audioFocus->direction.x = FLOAT_FROM_Q7( buffer[1] ); + audioFocus->direction.y = FLOAT_FROM_Q7( buffer[2] ); + audioFocus->direction.z = FLOAT_FROM_Q7( buffer[3] ); + + if ( numDataBytes == 5 ) + { + audioFocus->flvl = ( buffer[4] >> 4 ); + } + } +#else /* Audio Focus data is either 1, 8 or 9 bytes */ if ( numDataBytes != 1 && numDataBytes != 8 && numDataBytes != 9 ) { @@ -824,6 +1117,7 @@ static ivas_error unpackAudioFocusCommon( const uint8_t *buffer, uint32_t numDat audioFocus->flvl = ( buffer[8] >> 4 ); } } +#endif return IVAS_ERR_OK; } @@ -1467,6 +1761,9 @@ static const PACK_PI_FN packPiDataFuntions[IVAS_PI_MAX_ID] = { packISMGain, /* ISM_GAIN */ packISMOrientation, /* ISM_ORIENTATION */ packISMPosition, /* ISM_POSITION */ +#ifdef RTP_UPDATES_SA4_134 + packISMPositionCompact, /* ISM_POSITION_COMPACT */ +#endif packISMDistanceAttenuation, /* ISM_DISTANCE_ATTENUATION */ packISMDirectivity, /* ISM_DIRECTIVITY */ #else @@ -1483,13 +1780,19 @@ static const PACK_PI_FN packPiDataFuntions[IVAS_PI_MAX_ID] = { #else packUnsupportedData, /* DIEGETIC_TYPE */ #endif +#ifdef RTP_UPDATES_SA4_134 + packDynamicSuppression, /* DYNAMIC_AUDIO_SUPPRESSION_INDICATION */ +#else packUnsupportedData, /* RESERVED13 */ +#endif #ifdef RTP_S4_251135_CR26253_0016_REV1 packAudioFocusCommon, /* AUDIO_FOCUS_INDICATION */ #else packUnsupportedData, /* AUDIO_FOCUS_INDICATION */ #endif +#ifndef RTP_UPDATES_SA4_134 packUnsupportedData, /* RESERVED15 */ +#endif #ifdef RTP_S4_251135_CR26253_0016_REV1 packOrientation, /* PLAYBACK_DEVICE_ORIENTATION */ packOrientation, /* HEAD_ORIENTATION */ @@ -1498,7 +1801,11 @@ static const PACK_PI_FN packPiDataFuntions[IVAS_PI_MAX_ID] = { #else packListenerPosition, /* LISTENER_POSITION */ #endif +#ifdef RTP_UPDATES_SA4_134 + packDynamicSuppression, /* DYNAMIC_AUDIO_SUPPRESSION_REQUEST */ +#else packDynamicSuppression, /* DYNAMIC_AUDIO_SUPPRESSION */ +#endif packAudioFocusCommon, /* AUDIO_FOCUS_REQUEST */ #ifdef PI_LATENCY packPiLatency, /* PI_LATENCY */ @@ -1527,6 +1834,9 @@ static const PACK_PI_FN packPiDataFuntions[IVAS_PI_MAX_ID] = { #endif #ifdef REVERSE_ISM_PI_DATA packPosition, /* R_ISM_POSITION */ +#ifdef RTP_UPDATES_SA4_134 + packPositionCompact, /* R_ISM_POSITION_COMPACT */ +#endif packReverseISMDirection, /* R_ISM_DIRECTION */ #else packUnsupportedData, /* R_ISM_POSITION */ @@ -1535,7 +1845,9 @@ static const PACK_PI_FN packPiDataFuntions[IVAS_PI_MAX_ID] = { packUnsupportedData, /* RESERVED27 */ packUnsupportedData, /* RESERVED28 */ packUnsupportedData, /* RESERVED29 */ +#ifndef RTP_UPDATES_SA4_134 packUnsupportedData, /* RESERVED30 */ +#endif packNoPiData /* NO_DATA */ }; @@ -1555,6 +1867,9 @@ static const UNPACK_PI_FN unpackPiDataFuntions[IVAS_PI_MAX_ID] = { unpackISMGain, /* ISM_GAIN */ unpackISMOrientation, /* ISM_ORIENTATION */ unpackISMPosition, /* ISM_POSITION */ +#ifdef RTP_UPDATES_SA4_134 + unpackISMPositionCompact, /* ISM_POSITION_COMPACT */ +#endif unpackISMDistanceAttenuation, /* ISM_DISTANCE_ATTENUATION */ unpackISMDirectivity, /* ISM_DIRECTIVITY */ #else @@ -1571,13 +1886,19 @@ static const UNPACK_PI_FN unpackPiDataFuntions[IVAS_PI_MAX_ID] = { #else unpackUnsupportedData, /* DIEGETIC_TYPE */ #endif +#ifdef RTP_UPDATES_SA4_134 + unpackDynamicSuppression, /* DYNAMIC_AUDIO_SUPPRESSION_INDICATION */ +#else unpackUnsupportedData, /* RESERVED13 */ +#endif #ifdef RTP_S4_251135_CR26253_0016_REV1 unpackAudioFocusCommon, /* AUDIO_FOCUS_INDICATION */ #else unpackUnsupportedData, /* AUDIO_FOCUS_INDICATION */ #endif +#ifndef RTP_UPDATES_SA4_134 unpackUnsupportedData, /* RESERVED15 */ +#endif #ifdef RTP_S4_251135_CR26253_0016_REV1 unpackOrientation, /* PLAYBACK_DEVICE_ORIENTATION */ unpackOrientation, /* HEAD_ORIENTATION */ @@ -1586,7 +1907,11 @@ static const UNPACK_PI_FN unpackPiDataFuntions[IVAS_PI_MAX_ID] = { #else unpackListenerPosition, /* LISTENER_POSITION */ #endif +#ifdef RTP_UPDATES_SA4_134 + unpackDynamicSuppression, /* DYNAMIC_AUDIO_SUPPRESSION_REQUEST */ +#else unpackDynamicSuppression, /* DYNAMIC_AUDIO_SUPPRESSION */ +#endif unpackAudioFocusCommon, /* AUDIO_FOCUS_REQUEST */ #ifdef PI_LATENCY unpackPiLatency, /* PI_LATENCY */ @@ -1615,6 +1940,9 @@ static const UNPACK_PI_FN unpackPiDataFuntions[IVAS_PI_MAX_ID] = { #endif #ifdef REVERSE_ISM_PI_DATA unpackPosition, /* R_ISM_POSITION */ +#ifdef RTP_UPDATES_SA4_134 + unpackPositionCompact, /* R_ISM_POSITION_COMPACT */ +#endif unpackReverseISMDirection, /* R_ISM_DIRECTION */ #else unpackUnsupportedData, /* R_ISM_POSITION */ @@ -1623,10 +1951,48 @@ static const UNPACK_PI_FN unpackPiDataFuntions[IVAS_PI_MAX_ID] = { unpackUnsupportedData, /* RESERVED27 */ unpackUnsupportedData, /* RESERVED28 */ unpackUnsupportedData, /* RESERVED29 */ +#ifndef RTP_UPDATES_SA4_134 unpackUnsupportedData, /* RESERVED30 */ +#endif unpackNoPiData /* NO_DATA */ }; +#ifdef RTP_UPDATES_SA4_134 +static const uint32_t maxPiDataSize[IVAS_PI_MAX_ID] = { + 4, /* IVAS_PI_SCENE_ORIENTATION */ + 4, /* IVAS_PI_DEVICE_ORIENTATION_COMPENSATED */ + 4, /* IVAS_PI_DEVICE_ORIENTATION_UNCOMPENSATED */ + 8, /* IVAS_PI_ACOUSTIC_ENVIRONMENT */ + 5, /* IVAS_PI_AUDIO_DESCRIPTION */ + 1, /* IVAS_PI_ISM_NUM */ + 4, /* IVAS_PI_ISM_ID */ + 4, /* IVAS_PI_ISM_GAIN */ + 16, /* IVAS_PI_ISM_ORIENTATION */ + 24, /* IVAS_PI_ISM_POSITION */ + 16, /* IVAS_PI_ISM_POSITION_COMPACT */ + 12, /* IVAS_PI_ISM_DISTANCE_ATTENUATION */ + 8, /* IVAS_PI_ISM_DIRECTIVITY */ + 1, /* IVAS_PI_DIEGETIC_TYPE */ + 2, /* IVAS_PI_DYNAMIC_AUDIO_SUPPRESSION_INDICATION */ + 5, /* IVAS_PI_AUDIO_FOCUS_INDICATION */ + 4, /* IVAS_PI_PLAYBACK_DEVICE_ORIENTATION */ + 4, /* IVAS_PI_HEAD_ORIENTATION */ + 6, /* IVAS_PI_LISTENER_POSITION */ + 2, /* IVAS_PI_DYNAMIC_AUDIO_SUPPRESSION */ + 5, /* IVAS_PI_AUDIO_FOCUS_REQUEST */ + 4, /* IVAS_PI_PI_LATENCY */ + 1, /* IVAS_PI_R_ISM_ID */ + 1, /* IVAS_PI_R_ISM_GAIN */ + 4, /* IVAS_PI_R_ISM_ORIENTATION */ + 6, /* IVAS_PI_R_ISM_POSITION */ + 4, /* IVAS_PI_R_ISM_POSITION_COMPACT */ + 2, /* IVAS_PI_R_ISM_DIRECTION */ + 0, /* IVAS_PI_RESERVED27 */ + 0, /* IVAS_PI_RESERVED28 */ + 0, /* IVAS_PI_RESERVED29 */ + 0, /* NO_DATA */ +}; +#else static const uint32_t maxPiDataSize[IVAS_PI_MAX_ID] = { 8, /* IVAS_PI_SCENE_ORIENTATION */ 8, /* IVAS_PI_DEVICE_ORIENTATION_COMPENSATED */ @@ -1661,6 +2027,7 @@ static const uint32_t maxPiDataSize[IVAS_PI_MAX_ID] = { 0, /* IVAS_PI_RESERVED30 */ 0, /* IVAS_PI_NO_DATA = 31 */ }; +#endif ivas_error PI_PackData( const IVAS_PIDATA_GENERIC *piData, PIDATA_PACKED *packed, uint8_t pmBits ) { diff --git a/lib_util/ivas_rtp_pi_data.h b/lib_util/ivas_rtp_pi_data.h index 95a2ac9942..1c5d6d8c15 100644 --- a/lib_util/ivas_rtp_pi_data.h +++ b/lib_util/ivas_rtp_pi_data.h @@ -61,12 +61,17 @@ typedef enum IVAS_PI_ISM_GAIN, /* gain of each object */ IVAS_PI_ISM_ORIENTATION, /* orientation of each object */ IVAS_PI_ISM_POSITION, /* position of each object */ +#ifdef RTP_UPDATES_SA4_134 + IVAS_PI_ISM_POSITION_COMPACT, /* position of each object in compact representation */ +#endif IVAS_PI_ISM_DISTANCE_ATTENUATION, /* distance attenuation for each object */ IVAS_PI_ISM_DIRECTIVITY, /* directivity of each object */ IVAS_PI_DIEGETIC_TYPE, /* digetic audio indication */ IVAS_PI_DYNAMIC_AUDIO_SUPPRESSION_INDICATION, /* audio suppression indication */ IVAS_PI_AUDIO_FOCUS_INDICATION, /* audio focus indication (direction in Quaternions and/or level) */ +#ifndef RTP_UPDATES_SA4_134 IVAS_PI_RESERVED15, /* reserved */ +#endif /* Reverse direction PI types */ IVAS_PI_PLAYBACK_DEVICE_ORIENTATION, /* orientation of the playback device in quaternions */ @@ -79,11 +84,16 @@ typedef enum IVAS_PI_R_ISM_GAIN, /* editing request for gain factor for received object */ IVAS_PI_R_ISM_ORIENTATION, /* editing request for orientation for received object */ IVAS_PI_R_ISM_POSITION, /* editing request for position for received object */ +#ifdef RTP_UPDATES_SA4_134 + IVAS_PI_R_ISM_POSITION_COMPACT, /* editing request for position for received object in a compact representation*/ +#endif IVAS_PI_R_ISM_DIRECTION, /* editing request for direction for received object */ IVAS_PI_RESERVED27, /* reserved */ IVAS_PI_RESERVED28, /* reserved */ IVAS_PI_RESERVED29, /* reserved */ +#ifndef RTP_UPDATES_SA4_134 IVAS_PI_RESERVED30, /* reserved */ +#endif #endif /* RTP_S4_251135_CR26253_0016_REV1 */ IVAS_PI_NO_DATA = 31, /* Indicates an empty PI data frame */ IVAS_PI_MAX_ID /* Max number of PI data IDs supprted */ @@ -490,6 +500,7 @@ typedef union IVAS_PIDATA_ISM_GAIN ismGain; IVAS_PIDATA_ISM_ORIENTATION ismOrientation; IVAS_PIDATA_ISM_POSITION ismPosition; + IVAS_PIDATA_ISM_POSITION ismPositionCompact; IVAS_PIDATA_ISM_ATTENUATION ismAttenuation; IVAS_PIDATA_ISM_DIRECTIVITY ismDirectivity; IVAS_PIDATA_DIEGETIC digeticIndicator; @@ -514,6 +525,7 @@ typedef union #else IVAS_PIDATA_ISM_EDIT_POSITION ismEditPosition; #endif + IVAS_PIDATA_POSITION ismEditPositionCompact; 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 5b1bb2be79..f3d286aa58 100644 --- a/tests/rtp/ivasrtp.py +++ b/tests/rtp/ivasrtp.py @@ -174,12 +174,12 @@ class PIDATAS(str, Enum): ISM_GAIN = "ISM_GAIN" ISM_ORIENTATION = "ISM_ORIENTATION" ISM_POSITION = "ISM_POSITION" + ISM_POSITION_COMPACT = "ISM_POSITION_COMPACT" ISM_DISTANCE_ATTENUATION = "ISM_DISTANCE_ATTENUATION" ISM_DIRECTIVITY = "ISM_DIRECTIVITY" DIEGETIC_TYPE = "DIEGETIC_TYPE" DYNAMIC_AUDIO_SUPPRESSION_INDICATION = "DYNAMIC_AUDIO_SUPPRESSION_INDICATION" AUDIO_FOCUS_INDICATION = "AUDIO_FOCUS_INDICATION" - RESERVED15 = "RESERVED15" PLAYBACK_DEVICE_ORIENTATION = "PLAYBACK_DEVICE_ORIENTATION" HEAD_ORIENTATION = "HEAD_ORIENTATION" LISTENER_POSITION = "LISTENER_POSITION" @@ -190,11 +190,11 @@ class PIDATAS(str, Enum): R_ISM_GAIN = "R_ISM_GAIN" R_ISM_ORIENTATION = "R_ISM_ORIENTATION" R_ISM_POSITION = "R_ISM_POSITION" + R_ISM_POSITION_COMPACT = "R_ISM_POSITION_COMPACT" R_ISM_DIRECTION = "R_ISM_DIRECTION" RESERVED27 = "RESERVED27" RESERVED28 = "RESERVED28" RESERVED29 = "RESERVED29" - RESERVED30 = "RESERVED30" NO_PI_DATA = "NO_PI_DATA" @@ -409,6 +409,9 @@ class ISM_ORIENTATION: class ISM_POSITION: positions: list[POSITION] +class ISM_POSITION_COMPACT: + positions: list[POSITION] + @dataclass class DISTANCE_ATTENUATION: ref_dist: float = 1.0 @@ -727,6 +730,9 @@ cmrLookup = [ ] q15 = lambda x: int(min(32767.0, max(-32768.0, x * 32768.0))) +q11 = lambda x: int(min(2047.0, max(-2048.0, x * 2048.0))) +q10 = lambda x: int(min(1023.0, max(-1024.0, x * 1024.0))) +q7 = lambda x: int(min(127.0, max(-128.0, x * 128.0))) def unpackUnsupported(bitstrm: ConstBitStream, piSize: int) -> any: @@ -748,16 +754,16 @@ def packNoPiData(bitstrm: BitStream, data: any = None): def unpackOrientations(bitstrm: ConstBitStream, piSize: int) -> list[ORIENTATION]: assert ( - piSize % 8 - ) == 0 and piSize <= 32, "Incorrect PI Data Size for list[ORIENTATION]" + piSize % 4 + ) == 0 and piSize <= 16, "Incorrect PI Data Size for list[ORIENTATION]" orientations = list() while piSize > 0: - w = bitstrm.read(16).int / 32768.0 - x = bitstrm.read(16).int / 32768.0 - y = bitstrm.read(16).int / 32768.0 - z = bitstrm.read(16).int / 32768.0 + w = bitstrm.read(8).int / 128.0 + x = bitstrm.read(8).int / 128.0 + y = bitstrm.read(8).int / 128.0 + z = bitstrm.read(8).int / 128.0 orientations.append(ORIENTATION(w, x, y, z)) - piSize -= 8 + piSize -= 4 return orientations @@ -767,10 +773,10 @@ def packOrientations(bitstrm: BitStream, data: any): assert ( type(orientation) == ORIENTATION ), "Orientation PI Data expects a data of type list[ORIENTATION]" - bitstrm.append(f"intbe:16={q15(orientation.w)}") - bitstrm.append(f"intbe:16={q15(orientation.x)}") - bitstrm.append(f"intbe:16={q15(orientation.y)}") - bitstrm.append(f"intbe:16={q15(orientation.z)}") + bitstrm.append(f"intbe:8={q7(orientation.w)}") + bitstrm.append(f"intbe:8={q7(orientation.x)}") + bitstrm.append(f"intbe:8={q7(orientation.y)}") + bitstrm.append(f"intbe:8={q7(orientation.z)}") def unpackPositions(bitstrm: ConstBitStream, piSize: int) -> list[POSITION]: @@ -797,9 +803,32 @@ def packPositions(bitstrm: BitStream, data: any): bitstrm.append(f"intbe:16={q15(position.y / 327.68)}") bitstrm.append(f"intbe:16={q15(position.z / 327.68)}") +def unpackPositionsCompact(bitstrm: ConstBitStream, piSize: int) -> list[POSITION]: + assert piSize <= 16 and (piSize % 4) == 0, "Incorrect PI Data Size for Positions" + positions = list() + while piSize > 0: + x = bitstrm.read(11).int / 100.0 + y = bitstrm.read(11).int / 100.0 + z = bitstrm.read(10).int / 100.0 + positions.append(POSITION(x, y, z)) + piSize -= 4 + return positions + +def packPositionsCompact(bitstrm: BitStream, data: any): + assert type(data) == list, "Compact position PI Data expects a data of type list" + positions = cast(list, data) + assert len(positions) <= 4, "Max one compact position per ISM object" + for position in positions: + assert ( + type(position) == POSITION + ), "Compact position PI Data expects a data of type list[POSITIONS]" + bitstrm.append(f"intbe:11={q11(position.x / 20.48)}") + bitstrm.append(f"intbe:11={q11(position.y / 20.48)}") + bitstrm.append(f"intbe:10={q10(position.z / 10.24)}") + def unpackOrientation(bitstrm: ConstBitStream, piSize: int) -> ORIENTATION: - assert piSize == 8, "Incorrect PI Data Size for ORIENTATION" + assert piSize == 4, "Incorrect PI Data Size for ORIENTATION" orientations = unpackOrientations(bitstrm, piSize) assert len(orientations) == 1 return orientations[0] @@ -825,6 +854,16 @@ def packPosition(bitstrm: BitStream, data: any): position = cast(POSITION, data) packPositions(bitstrm, [position]) +def unpackPositionCompact(bitstrm: ConstBitStream, piSize: int) -> POSITION: + assert piSize == 4, "Incorrect PI Data Size for compact POSITION" + positions = unpackPositionsCompact(bitstrm, piSize) + assert len(positions) == 1 + return positions[0] + +def packPositionCompact(bitstrm: BitStream, data: any): + assert type(data) == POSITION, "Compact position PI Data expects a data of type POSITION" + position = cast(POSITION, data) + packPositionsCompact(bitstrm, [position]) def unpackAudioDescription( bitstrm: ConstBitStream, piSize: int @@ -975,7 +1014,7 @@ def packAcousticEnv(bitstrm: BitStream, data: any): def unpackAudioFocus(bitstrm: ConstBitStream, piSize: int) -> AUDIO_FOCUS: assert ( - piSize == 1 or piSize == 8 or piSize == 9 + piSize == 1 or piSize == 4 or piSize == 5 ), "Incorrect PI Data Size for AUDIO_FOCUS" direction = None level = None @@ -983,8 +1022,8 @@ def unpackAudioFocus(bitstrm: ConstBitStream, piSize: int) -> AUDIO_FOCUS: level = bitstrm.read(4).uint _ = bitstrm.read(4) else: - direction = unpackOrientation(bitstrm, 8) - if piSize == 9: + direction = unpackOrientation(bitstrm, 4) + if piSize == 5: level = bitstrm.read(4).uint _ = bitstrm.read(4) @@ -1166,12 +1205,12 @@ PIDataUnpacker = [ unpackISMGain, # ISM_GAIN unpackOrientations, # ISM_ORIENTATION unpackPositions, # ISM_POSITION + unpackPositionsCompact, # ISM_POSITION_COMPACT unpackISMDistanceAttenuation, # ISM_DISTANCE_ATTENUATION unpackISMDirectivity, # ISM_DIRECTIVITY unpackDiegetic, # DIEGETIC_TYPE unpackDAS, # DYNAMIC_AUDIO_SUPPRESSION_INDICATION unpackAudioFocus, # AUDIO_FOCUS_INDICATION - unpackUnsupported, # RESERVED15 unpackOrientation, # PLAYBACK_DEVICE_ORIENTATION unpackOrientation, # HEAD_ORIENTATION unpackPosition, # LISTENER_POSITION @@ -1182,11 +1221,11 @@ PIDataUnpacker = [ unpackReverseISMGain, # R_ISM_GAIN unpackOrientation, # R_ISM_ORIENTATION unpackPosition, # R_ISM_POSITION + unpackPositionCompact, # R_ISM_POSITION_COMPACT unpackReverseISMDirection, # R_ISM_DIRECTION unpackUnsupported, # RESERVED27 unpackUnsupported, # RESERVED28 unpackUnsupported, # RESERVED29 - unpackUnsupported, # RESERVED30 unpackNoPiData, # NO_DATA ] @@ -1201,12 +1240,12 @@ PIDataPacker = [ packISMGain, # ISM_GAIN packOrientations, # ISM_ORIENTATION packPositions, # ISM_POSITION + packPositionsCompact, # ISM_POSITION_COMPACT packISMDistanceAttenuation, # ISM_DISTANCE_ATTENUATION packISMDirectivity, # ISM_DIRECTIVITY packDiegetic, # DIEGETIC_TYPE packDAS, # DYNAMIC_AUDIO_SUPPRESSION_INDICATION packAudioFocus, # AUDIO_FOCUS_INDICATION - packUnsupported, # RESERVED15 packOrientation, # PLAYBACK_DEVICE_ORIENTATION packOrientation, # HEAD_ORIENTATION packPosition, # LISTENER_POSITION @@ -1217,11 +1256,11 @@ PIDataPacker = [ packReverseISMGain, # R_ISM_GAIN packOrientation, # R_ISM_ORIENTATION packPosition, # R_ISM_POSITION + packPositionCompact, # R_ISM_POSITION_COMPACT packReverseISMDirection, # R_ISM_DIRECTION packUnsupported, # RESERVED27 packUnsupported, # RESERVED28 packUnsupported, # RESERVED29 - packUnsupported, # RESERVED30 packNoPiData, # NO_DATA ] -- GitLab From 5572ee2c80e19693148898627a54c28feb6bfe62 Mon Sep 17 00:00:00 2001 From: Lauros Pajunen Date: Tue, 18 Nov 2025 23:54:15 -0600 Subject: [PATCH 02/24] Fix pi size parsing, add threshold for orientation parsing --- lib_util/ivas_rtp_payload.c | 6 ++++-- lib_util/ivas_rtp_pi_data.c | 12 ++++++------ tests/rtp/test_rtp.py | 8 ++++---- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/lib_util/ivas_rtp_payload.c b/lib_util/ivas_rtp_payload.c index ce529094f0..6a816f36de 100644 --- a/lib_util/ivas_rtp_payload.c +++ b/lib_util/ivas_rtp_payload.c @@ -1568,6 +1568,7 @@ static ivas_error parsePIData( IVAS_RTP_UNPACK_HANDLE hUnpack, uint32_t rtpTimes { bool PF = true; uint32_t nBytes = *numBytes; + bool isFirstPiSize = true; while ( PF ) { @@ -1589,12 +1590,13 @@ static ivas_error parsePIData( IVAS_RTP_UNPACK_HANDLE hUnpack, uint32_t rtpTimes do { byte = payload->buffer[nBytes++]; - piSize += ( byte & MASK_5BIT ); + piSize += isFirstPiSize ? ( byte & MASK_5BIT ) : byte; if ( nBytes >= payload->length ) { return IVAS_ERROR( IVAS_ERR_RTP_UNDERFLOW, "Underflow during reading piSize" ); } - } while ( byte == 32 ); + isFirstPiSize = false; + } while ( byte == 255 || piSize == 32 ); #else do { diff --git a/lib_util/ivas_rtp_pi_data.c b/lib_util/ivas_rtp_pi_data.c index e8a7d05304..de17cf8940 100644 --- a/lib_util/ivas_rtp_pi_data.c +++ b/lib_util/ivas_rtp_pi_data.c @@ -111,12 +111,12 @@ static int16_t ivasPayload_convertToQ10( float value ) * * Convert a float value into a Q7 encoded value. *-----------------------------------------------------------------------*/ -static int16_t ivasPayload_convertToQ7( float value ) +static int8_t ivasPayload_convertToQ7( float value ) { value = ( value * 128.0f ); value = value > +128.0f ? +128.0f : value; value = value < -128.0f ? -128.0f : value; - return (int16_t) ( value ); + return (int8_t) ( value ); } #endif @@ -210,10 +210,10 @@ static ivas_error packOrientation( const IVAS_PIDATA_GENERIC *piData, uint8_t *b buffer[nBytes++] = ( orientation->piDataType & MASK_5BIT ); /* PF/PM populated during final packing */ #ifdef RTP_UPDATES_SA4_134 buffer[nBytes++] = 4; - buffer[nBytes++] = (uint8_t) ivasPayload_convertToQ7( orientation->orientation.w ); - buffer[nBytes++] = (uint8_t) ivasPayload_convertToQ7( orientation->orientation.x ); - buffer[nBytes++] = (uint8_t) ivasPayload_convertToQ7( orientation->orientation.y ); - buffer[nBytes++] = (uint8_t) ivasPayload_convertToQ7( orientation->orientation.z ); + buffer[nBytes++] = ivasPayload_convertToQ7( orientation->orientation.w ); + buffer[nBytes++] = ivasPayload_convertToQ7( orientation->orientation.x ); + buffer[nBytes++] = ivasPayload_convertToQ7( orientation->orientation.y ); + buffer[nBytes++] = ivasPayload_convertToQ7( orientation->orientation.z ); #else buffer[nBytes++] = 8; nBytes = writeInt16( buffer, nBytes, ivasPayload_convertToQ15( orientation->orientation.w ) ); diff --git a/tests/rtp/test_rtp.py b/tests/rtp/test_rtp.py index 53cb6488c5..3c2550c363 100644 --- a/tests/rtp/test_rtp.py +++ b/tests/rtp/test_rtp.py @@ -322,10 +322,10 @@ def isEqualFrame(refFrame: bytes, dutFrame: bytes): def isEqualOrientation(ref: ORIENTATION, dut: ORIENTATION): - assert abs(ref.w - dut.w) < 0.0001, "Scene Orientation PI Data mismatch in w" - assert abs(ref.x - dut.x) < 0.0001, "Scene Orientation PI Data mismatch in x" - assert abs(ref.y - dut.y) < 0.0001, "Scene Orientation PI Data mismatch in y" - assert abs(ref.z - dut.z) < 0.0001, "Scene Orientation PI Data mismatch in z" + assert abs(ref.w - dut.w) < 0.0079, "Scene Orientation PI Data mismatch in w" + assert abs(ref.x - dut.x) < 0.0079, "Scene Orientation PI Data mismatch in x" + assert abs(ref.y - dut.y) < 0.0079, "Scene Orientation PI Data mismatch in y" + assert abs(ref.z - dut.z) < 0.0079, "Scene Orientation PI Data mismatch in z" def isEqualPosition(ref: POSITION, dut: POSITION): -- GitLab From 92054c0a647c2f27e7ccbabb51db90715c97697c Mon Sep 17 00:00:00 2001 From: Lauros Pajunen Date: Wed, 19 Nov 2025 00:13:39 -0600 Subject: [PATCH 03/24] Clang format --- lib_util/ivas_rtp_internal.h | 8 +++--- lib_util/ivas_rtp_pi_data.c | 54 ++++++++++++++++++------------------ lib_util/ivas_rtp_pi_data.h | 34 +++++++++++------------ 3 files changed, 48 insertions(+), 48 deletions(-) diff --git a/lib_util/ivas_rtp_internal.h b/lib_util/ivas_rtp_internal.h index 78f416879f..41d8ae465e 100644 --- a/lib_util/ivas_rtp_internal.h +++ b/lib_util/ivas_rtp_internal.h @@ -75,10 +75,10 @@ enum MASK_BITS #define FLOAT_FROM_Q15( q15Val ) ( (float) ( q15Val ) / 32768.0f ) #ifdef RTP_UPDATES_SA4_134 #define MAX_PI_COMPACT_POSITION_XY_METERS ( 10.24f ) -#define MAX_PI_COMPACT_POSITION_Z_METERS ( 5.12f ) -#define FLOAT_FROM_Q11( q11Val ) ( (float) ( q11Val ) / 2048.0f ) -#define FLOAT_FROM_Q10( q10Val ) ( (float) ( q10Val ) / 1024.0f ) -#define FLOAT_FROM_Q7( q7Val ) ( (float) ( q7Val ) / 128.0f ) +#define MAX_PI_COMPACT_POSITION_Z_METERS ( 5.12f ) +#define FLOAT_FROM_Q11( q11Val ) ( (float) ( q11Val ) / 2048.0f ) +#define FLOAT_FROM_Q10( q10Val ) ( (float) ( q10Val ) / 1024.0f ) +#define FLOAT_FROM_Q7( q7Val ) ( (float) ( q7Val ) / 128.0f ) #endif extern const float mapDSR[1u << NBITS_DSR]; diff --git a/lib_util/ivas_rtp_pi_data.c b/lib_util/ivas_rtp_pi_data.c index de17cf8940..eccae53c0a 100644 --- a/lib_util/ivas_rtp_pi_data.c +++ b/lib_util/ivas_rtp_pi_data.c @@ -1756,13 +1756,13 @@ static const PACK_PI_FN packPiDataFuntions[IVAS_PI_MAX_ID] = { packUnsupportedData, /* AUDIO_DESCRIPTION */ #endif /* RTP_S4_251135_CR26253_0016_REV1 */ #ifdef ISM_PI_DATA - packISMNum, /* ISM_NUM */ - packISMID, /* ISM_ID */ - packISMGain, /* ISM_GAIN */ - packISMOrientation, /* ISM_ORIENTATION */ - packISMPosition, /* ISM_POSITION */ + packISMNum, /* ISM_NUM */ + packISMID, /* ISM_ID */ + packISMGain, /* ISM_GAIN */ + packISMOrientation, /* ISM_ORIENTATION */ + packISMPosition, /* ISM_POSITION */ #ifdef RTP_UPDATES_SA4_134 - packISMPositionCompact, /* ISM_POSITION_COMPACT */ + packISMPositionCompact, /* ISM_POSITION_COMPACT */ #endif packISMDistanceAttenuation, /* ISM_DISTANCE_ATTENUATION */ packISMDirectivity, /* ISM_DIRECTIVITY */ @@ -1783,7 +1783,7 @@ static const PACK_PI_FN packPiDataFuntions[IVAS_PI_MAX_ID] = { #ifdef RTP_UPDATES_SA4_134 packDynamicSuppression, /* DYNAMIC_AUDIO_SUPPRESSION_INDICATION */ #else - packUnsupportedData, /* RESERVED13 */ + packUnsupportedData, /* RESERVED13 */ #endif #ifdef RTP_S4_251135_CR26253_0016_REV1 packAudioFocusCommon, /* AUDIO_FOCUS_INDICATION */ @@ -1799,18 +1799,18 @@ static const PACK_PI_FN packPiDataFuntions[IVAS_PI_MAX_ID] = { #ifdef REVERSE_ISM_PI_DATA packPosition, /* LISTENER_POSITION */ #else - packListenerPosition, /* LISTENER_POSITION */ + packListenerPosition, /* LISTENER_POSITION */ #endif #ifdef RTP_UPDATES_SA4_134 packDynamicSuppression, /* DYNAMIC_AUDIO_SUPPRESSION_REQUEST */ #else - packDynamicSuppression, /* DYNAMIC_AUDIO_SUPPRESSION */ + packDynamicSuppression, /* DYNAMIC_AUDIO_SUPPRESSION */ #endif - packAudioFocusCommon, /* AUDIO_FOCUS_REQUEST */ + packAudioFocusCommon, /* AUDIO_FOCUS_REQUEST */ #ifdef PI_LATENCY packPiLatency, /* PI_LATENCY */ #else - packUnsupportedData, /* PI_LATENCY */ + packUnsupportedData, /* PI_LATENCY */ #endif #else packUnsupportedData, /* PLAYBACK_DEVICE_ORIENTATION */ @@ -1833,9 +1833,9 @@ 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 */ #ifdef RTP_UPDATES_SA4_134 - packPositionCompact, /* R_ISM_POSITION_COMPACT */ + packPositionCompact, /* R_ISM_POSITION_COMPACT */ #endif packReverseISMDirection, /* R_ISM_DIRECTION */ #else @@ -1848,7 +1848,7 @@ static const PACK_PI_FN packPiDataFuntions[IVAS_PI_MAX_ID] = { #ifndef RTP_UPDATES_SA4_134 packUnsupportedData, /* RESERVED30 */ #endif - packNoPiData /* NO_DATA */ + packNoPiData /* NO_DATA */ }; static const UNPACK_PI_FN unpackPiDataFuntions[IVAS_PI_MAX_ID] = { @@ -1862,13 +1862,13 @@ static const UNPACK_PI_FN unpackPiDataFuntions[IVAS_PI_MAX_ID] = { unpackUnsupportedData, /* AUDIO_DESCRIPTION */ #endif #ifdef ISM_PI_DATA - unpackISMNum, /* ISM_NUM */ - unpackISMID, /* ISM_ID */ - unpackISMGain, /* ISM_GAIN */ - unpackISMOrientation, /* ISM_ORIENTATION */ - unpackISMPosition, /* ISM_POSITION */ + unpackISMNum, /* ISM_NUM */ + unpackISMID, /* ISM_ID */ + unpackISMGain, /* ISM_GAIN */ + unpackISMOrientation, /* ISM_ORIENTATION */ + unpackISMPosition, /* ISM_POSITION */ #ifdef RTP_UPDATES_SA4_134 - unpackISMPositionCompact, /* ISM_POSITION_COMPACT */ + unpackISMPositionCompact, /* ISM_POSITION_COMPACT */ #endif unpackISMDistanceAttenuation, /* ISM_DISTANCE_ATTENUATION */ unpackISMDirectivity, /* ISM_DIRECTIVITY */ @@ -1887,7 +1887,7 @@ static const UNPACK_PI_FN unpackPiDataFuntions[IVAS_PI_MAX_ID] = { unpackUnsupportedData, /* DIEGETIC_TYPE */ #endif #ifdef RTP_UPDATES_SA4_134 - unpackDynamicSuppression, /* DYNAMIC_AUDIO_SUPPRESSION_INDICATION */ + unpackDynamicSuppression, /* DYNAMIC_AUDIO_SUPPRESSION_INDICATION */ #else unpackUnsupportedData, /* RESERVED13 */ #endif @@ -1905,18 +1905,18 @@ static const UNPACK_PI_FN unpackPiDataFuntions[IVAS_PI_MAX_ID] = { #ifdef REVERSE_ISM_PI_DATA unpackPosition, /* LISTENER_POSITION */ #else - unpackListenerPosition, /* LISTENER_POSITION */ + unpackListenerPosition, /* LISTENER_POSITION */ #endif #ifdef RTP_UPDATES_SA4_134 unpackDynamicSuppression, /* DYNAMIC_AUDIO_SUPPRESSION_REQUEST */ #else unpackDynamicSuppression, /* DYNAMIC_AUDIO_SUPPRESSION */ #endif - unpackAudioFocusCommon, /* AUDIO_FOCUS_REQUEST */ + unpackAudioFocusCommon, /* AUDIO_FOCUS_REQUEST */ #ifdef PI_LATENCY unpackPiLatency, /* PI_LATENCY */ #else - unpackUnsupportedData, /* PI_LATENCY */ + unpackUnsupportedData, /* PI_LATENCY */ #endif #else unpackUnsupportedData, /* PLAYBACK_DEVICE_ORIENTATION */ @@ -1939,9 +1939,9 @@ 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 */ #ifdef RTP_UPDATES_SA4_134 - unpackPositionCompact, /* R_ISM_POSITION_COMPACT */ + unpackPositionCompact, /* R_ISM_POSITION_COMPACT */ #endif unpackReverseISMDirection, /* R_ISM_DIRECTION */ #else @@ -1954,7 +1954,7 @@ static const UNPACK_PI_FN unpackPiDataFuntions[IVAS_PI_MAX_ID] = { #ifndef RTP_UPDATES_SA4_134 unpackUnsupportedData, /* RESERVED30 */ #endif - unpackNoPiData /* NO_DATA */ + unpackNoPiData /* NO_DATA */ }; #ifdef RTP_UPDATES_SA4_134 diff --git a/lib_util/ivas_rtp_pi_data.h b/lib_util/ivas_rtp_pi_data.h index 1c5d6d8c15..fa319c6b2e 100644 --- a/lib_util/ivas_rtp_pi_data.h +++ b/lib_util/ivas_rtp_pi_data.h @@ -55,14 +55,14 @@ typedef enum IVAS_PI_DEVICE_ORIENTATION_UNCOMPENSATED, /* orientation of device in unit quaternions (un-compensated) */ IVAS_PI_ACOUSTIC_ENVIRONMENT, /* describe the acoustic environment */ #ifdef RTP_S4_251135_CR26253_0016_REV1 - IVAS_PI_AUDIO_DESCRIPTION, /* audio content description (voice/music/ambiance) */ - IVAS_PI_ISM_NUM, /* Number of objects */ - IVAS_PI_ISM_ID, /* id of each object */ - IVAS_PI_ISM_GAIN, /* gain of each object */ - IVAS_PI_ISM_ORIENTATION, /* orientation of each object */ - IVAS_PI_ISM_POSITION, /* position of each object */ + IVAS_PI_AUDIO_DESCRIPTION, /* audio content description (voice/music/ambiance) */ + IVAS_PI_ISM_NUM, /* Number of objects */ + IVAS_PI_ISM_ID, /* id of each object */ + IVAS_PI_ISM_GAIN, /* gain of each object */ + IVAS_PI_ISM_ORIENTATION, /* orientation of each object */ + IVAS_PI_ISM_POSITION, /* position of each object */ #ifdef RTP_UPDATES_SA4_134 - IVAS_PI_ISM_POSITION_COMPACT, /* position of each object in compact representation */ + IVAS_PI_ISM_POSITION_COMPACT, /* position of each object in compact representation */ #endif IVAS_PI_ISM_DISTANCE_ATTENUATION, /* distance attenuation for each object */ IVAS_PI_ISM_DIRECTIVITY, /* directivity of each object */ @@ -70,7 +70,7 @@ typedef enum IVAS_PI_DYNAMIC_AUDIO_SUPPRESSION_INDICATION, /* audio suppression indication */ IVAS_PI_AUDIO_FOCUS_INDICATION, /* audio focus indication (direction in Quaternions and/or level) */ #ifndef RTP_UPDATES_SA4_134 - IVAS_PI_RESERVED15, /* reserved */ + IVAS_PI_RESERVED15, /* reserved */ #endif /* Reverse direction PI types */ @@ -85,18 +85,18 @@ typedef enum IVAS_PI_R_ISM_ORIENTATION, /* editing request for orientation for received object */ IVAS_PI_R_ISM_POSITION, /* editing request for position for received object */ #ifdef RTP_UPDATES_SA4_134 - IVAS_PI_R_ISM_POSITION_COMPACT, /* editing request for position for received object in a compact representation*/ + IVAS_PI_R_ISM_POSITION_COMPACT, /* editing request for position for received object in a compact representation*/ #endif - IVAS_PI_R_ISM_DIRECTION, /* editing request for direction for received object */ - IVAS_PI_RESERVED27, /* reserved */ - IVAS_PI_RESERVED28, /* reserved */ - IVAS_PI_RESERVED29, /* reserved */ + IVAS_PI_R_ISM_DIRECTION, /* editing request for direction for received object */ + IVAS_PI_RESERVED27, /* reserved */ + IVAS_PI_RESERVED28, /* reserved */ + IVAS_PI_RESERVED29, /* reserved */ #ifndef RTP_UPDATES_SA4_134 - IVAS_PI_RESERVED30, /* reserved */ + IVAS_PI_RESERVED30, /* reserved */ #endif -#endif /* RTP_S4_251135_CR26253_0016_REV1 */ - IVAS_PI_NO_DATA = 31, /* Indicates an empty PI data frame */ - IVAS_PI_MAX_ID /* Max number of PI data IDs supprted */ +#endif /* RTP_S4_251135_CR26253_0016_REV1 */ + IVAS_PI_NO_DATA = 31, /* Indicates an empty PI data frame */ + IVAS_PI_MAX_ID /* Max number of PI data IDs supprted */ } IVAS_PI_TYPE; /* cartesian coordinates (X,Y,Z) in 3D space */ -- GitLab From eb2f69a6cb78fdf06b0c22f02068ffda34274e5a Mon Sep 17 00:00:00 2001 From: Lauros Pajunen Date: Wed, 19 Nov 2025 08:28:33 -0600 Subject: [PATCH 04/24] Fix orientation packing, add thersholds to tests --- lib_util/ivas_rtp_pi_data.c | 32 ++++++++++++++++---------------- tests/rtp/test_rtp.py | 8 ++++---- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/lib_util/ivas_rtp_pi_data.c b/lib_util/ivas_rtp_pi_data.c index eccae53c0a..8490c907bb 100644 --- a/lib_util/ivas_rtp_pi_data.c +++ b/lib_util/ivas_rtp_pi_data.c @@ -210,10 +210,10 @@ static ivas_error packOrientation( const IVAS_PIDATA_GENERIC *piData, uint8_t *b buffer[nBytes++] = ( orientation->piDataType & MASK_5BIT ); /* PF/PM populated during final packing */ #ifdef RTP_UPDATES_SA4_134 buffer[nBytes++] = 4; - buffer[nBytes++] = ivasPayload_convertToQ7( orientation->orientation.w ); - buffer[nBytes++] = ivasPayload_convertToQ7( orientation->orientation.x ); - buffer[nBytes++] = ivasPayload_convertToQ7( orientation->orientation.y ); - buffer[nBytes++] = ivasPayload_convertToQ7( orientation->orientation.z ); + buffer[nBytes++] = (uint8_t) ivasPayload_convertToQ7( orientation->orientation.w ); + buffer[nBytes++] = (uint8_t) ivasPayload_convertToQ7( orientation->orientation.x ); + buffer[nBytes++] = (uint8_t) ivasPayload_convertToQ7( orientation->orientation.y ); + buffer[nBytes++] = (uint8_t) ivasPayload_convertToQ7( orientation->orientation.z ); #else buffer[nBytes++] = 8; nBytes = writeInt16( buffer, nBytes, ivasPayload_convertToQ15( orientation->orientation.w ) ); @@ -294,10 +294,10 @@ static ivas_error unpackOrientation( const uint8_t *buffer, uint32_t numDataByte } piData->size = sizeof( IVAS_PIDATA_ORIENTATION ); - orientation->orientation.w = FLOAT_FROM_Q7( buffer[0] ); - orientation->orientation.x = FLOAT_FROM_Q7( buffer[1] ); - orientation->orientation.y = FLOAT_FROM_Q7( buffer[2] ); - orientation->orientation.z = FLOAT_FROM_Q7( buffer[3] ); + orientation->orientation.w = FLOAT_FROM_Q7( (int8_t) buffer[0] ); + orientation->orientation.x = FLOAT_FROM_Q7( (int8_t) buffer[1] ); + orientation->orientation.y = FLOAT_FROM_Q7( (int8_t) buffer[2] ); + orientation->orientation.z = FLOAT_FROM_Q7( (int8_t) buffer[3] ); #else /* Orientation data is 8 bytes */ if ( numDataBytes != 8 ) @@ -333,10 +333,10 @@ static ivas_error unpackISMOrientation( const uint8_t *buffer, uint32_t numDataB for ( n = 0; n < ism_orientation->numObjects; n++ ) { - ism_orientation->orientation[n].w = FLOAT_FROM_Q7( buffer[4 * n] ); - ism_orientation->orientation[n].x = FLOAT_FROM_Q7( buffer[4 * n + 1] ); - ism_orientation->orientation[n].y = FLOAT_FROM_Q7( buffer[4 * n + 2] ); - ism_orientation->orientation[n].z = FLOAT_FROM_Q7( buffer[4 * n + 3] ); + ism_orientation->orientation[n].w = FLOAT_FROM_Q7( (int8_t) buffer[4 * n] ); + ism_orientation->orientation[n].x = FLOAT_FROM_Q7( (int8_t) buffer[4 * n + 1] ); + ism_orientation->orientation[n].y = FLOAT_FROM_Q7( (int8_t) buffer[4 * n + 2] ); + ism_orientation->orientation[n].z = FLOAT_FROM_Q7( (int8_t) buffer[4 * n + 3] ); } #else /* Orientation data is 8 bytes */ @@ -1080,10 +1080,10 @@ static ivas_error unpackAudioFocusCommon( const uint8_t *buffer, uint32_t numDat } else { - audioFocus->direction.w = FLOAT_FROM_Q7( buffer[0] ); - audioFocus->direction.x = FLOAT_FROM_Q7( buffer[1] ); - audioFocus->direction.y = FLOAT_FROM_Q7( buffer[2] ); - audioFocus->direction.z = FLOAT_FROM_Q7( buffer[3] ); + audioFocus->direction.w = FLOAT_FROM_Q7( (int8_t) buffer[0] ); + audioFocus->direction.x = FLOAT_FROM_Q7( (int8_t) buffer[1] ); + audioFocus->direction.y = FLOAT_FROM_Q7( (int8_t) buffer[2] ); + audioFocus->direction.z = FLOAT_FROM_Q7( (int8_t) buffer[3] ); if ( numDataBytes == 5 ) { diff --git a/tests/rtp/test_rtp.py b/tests/rtp/test_rtp.py index 3c2550c363..bb57259eaa 100644 --- a/tests/rtp/test_rtp.py +++ b/tests/rtp/test_rtp.py @@ -392,16 +392,16 @@ def isEqualAudioFocus(ref: AUDIO_FOCUS, dut: AUDIO_FOCUS): assert dut.direction is not None, "Audio Focus PI Data missing direction" if ref.direction is not None and dut.direction is not None: assert ( - abs(ref.direction["w"] - dut.direction.w) < 0.0001 + abs(ref.direction["w"] - dut.direction.w) < 0.0079 ), "Audio Focus PI Data mismatch in direction w" assert ( - abs(ref.direction["x"] - dut.direction.x) < 0.0001 + abs(ref.direction["x"] - dut.direction.x) < 0.0079 ), "Audio Focus PI Data mismatch in direction x" assert ( - abs(ref.direction["y"] - dut.direction.y) < 0.0001 + abs(ref.direction["y"] - dut.direction.y) < 0.0079 ), "Audio Focus PI Data mismatch in direction y" assert ( - abs(ref.direction["z"] - dut.direction.z) < 0.0001 + abs(ref.direction["z"] - dut.direction.z) < 0.0079 ), "Audio Focus PI Data mismatch in direction z" assert ref.level == dut.level, "Audio Focus PI Data mismatch in level" -- GitLab From 7a3ebeb647711b37c4acffb1624c634a2bb30570 Mon Sep 17 00:00:00 2001 From: Lauros Pajunen Date: Wed, 19 Nov 2025 10:23:41 -0600 Subject: [PATCH 05/24] Fixes to compact position PI packing and unpacking, add tests for compact position PI --- lib_util/ivas_rtp_internal.h | 2 +- lib_util/ivas_rtp_pi_data.c | 58 ++++++++++++++++++------------------ tests/rtp/ivasrtp.py | 8 ++--- tests/rtp/test_rtp.py | 8 +++++ 4 files changed, 42 insertions(+), 34 deletions(-) diff --git a/lib_util/ivas_rtp_internal.h b/lib_util/ivas_rtp_internal.h index 41d8ae465e..007730217a 100644 --- a/lib_util/ivas_rtp_internal.h +++ b/lib_util/ivas_rtp_internal.h @@ -76,8 +76,8 @@ enum MASK_BITS #ifdef RTP_UPDATES_SA4_134 #define MAX_PI_COMPACT_POSITION_XY_METERS ( 10.24f ) #define MAX_PI_COMPACT_POSITION_Z_METERS ( 5.12f ) -#define FLOAT_FROM_Q11( q11Val ) ( (float) ( q11Val ) / 2048.0f ) #define FLOAT_FROM_Q10( q10Val ) ( (float) ( q10Val ) / 1024.0f ) +#define FLOAT_FROM_Q9( q9Val ) ( (float) ( q9Val ) / 512.0f ) #define FLOAT_FROM_Q7( q7Val ) ( (float) ( q7Val ) / 128.0f ) #endif diff --git a/lib_util/ivas_rtp_pi_data.c b/lib_util/ivas_rtp_pi_data.c index 8490c907bb..0590232110 100644 --- a/lib_util/ivas_rtp_pi_data.c +++ b/lib_util/ivas_rtp_pi_data.c @@ -81,28 +81,28 @@ static int16_t ivasPayload_convertToQ15( float value ) #ifdef RTP_UPDATES_SA4_134 /*-----------------------------------------------------------------------* - * ivasPayload_convertToQ11() + * ivasPayload_convertToQ10() * - * Convert a float value into a Q11 encoded value. + * Convert a float value into a Q10 encoded value. *-----------------------------------------------------------------------*/ -static int16_t ivasPayload_convertToQ11( float value ) +static int16_t ivasPayload_convertToQ10( float value ) { - value = ( value * 2048.0f ); - value = value > +2048.0f ? +2048.0f : value; - value = value < -2048.0f ? -2048.0f : value; + value = ( value * 1024.0f ); + value = value > +1024.0f ? +1024.0f : value; + value = value < -1024.0f ? -1024.0f : value; return (int16_t) ( value ); } /*-----------------------------------------------------------------------* - * ivasPayload_convertToQ10() + * ivasPayload_convertToQ9() * - * Convert a float value into a Q10 encoded value. + * Convert a float value into a Q9 encoded value. *-----------------------------------------------------------------------*/ -static int16_t ivasPayload_convertToQ10( float value ) +static int16_t ivasPayload_convertToQ9( float value ) { - value = ( value * 1024.0f ); - value = value > +1024.0f ? +1024.0f : value; - value = value < -1024.0f ? -1024.0f : value; + value = ( value * 512.0f ); + value = value > +512.0f ? +512.0f : value; + value = value < -512.0f ? -512.0f : value; return (int16_t) ( value ); } @@ -751,9 +751,9 @@ static ivas_error packPositionCompact( const IVAS_PIDATA_GENERIC *piData, uint8_ buffer[nBytes++] = ( position->piDataType & MASK_5BIT ); /* PF/PM populated during final packing */ buffer[nBytes++] = 4; - posX = (uint16_t) ivasPayload_convertToQ11( position->position.x / MAX_PI_COMPACT_POSITION_XY_METERS ); - posY = (uint16_t) ivasPayload_convertToQ11( position->position.y / MAX_PI_COMPACT_POSITION_XY_METERS ); - posZ = (uint16_t) ivasPayload_convertToQ10( position->position.z / MAX_PI_COMPACT_POSITION_Z_METERS ); + posX = (uint16_t) ivasPayload_convertToQ10( position->position.x / MAX_PI_COMPACT_POSITION_XY_METERS ); + posY = (uint16_t) ivasPayload_convertToQ10( position->position.y / MAX_PI_COMPACT_POSITION_XY_METERS ); + posZ = (uint16_t) ivasPayload_convertToQ9( position->position.z / MAX_PI_COMPACT_POSITION_Z_METERS ); buffer[nBytes++] = (uint8_t) ( posX >> 8 ); buffer[nBytes++] = (uint8_t) ( ( ( posX & MASK_3BIT ) << 5 ) | posY >> 6 ); buffer[nBytes++] = (uint8_t) ( ( ( posY & MASK_6BIT ) << 2 ) | posZ >> 8 ); @@ -767,7 +767,7 @@ static ivas_error packPositionCompact( const IVAS_PIDATA_GENERIC *piData, uint8_ static ivas_error unpackPositionCompact( const uint8_t *buffer, uint32_t numDataBytes, IVAS_PIDATA_GENERIC *piData ) { IVAS_PIDATA_POSITION *position = (IVAS_PIDATA_POSITION *) piData; - uint32_t compactRead = 0; + int32_t compactRead = 0; /* Compact position data is 4 bytes */ if ( numDataBytes != 4 ) @@ -777,10 +777,10 @@ static ivas_error unpackPositionCompact( const uint8_t *buffer, uint32_t numData position->size = sizeof( IVAS_PIDATA_POSITION ); - compactRead = ( (uint32_t) buffer[0] << 24 ) | ( (uint32_t) buffer[1] << 16 ) | ( (uint32_t) buffer[2] << 8 ) | ( (uint32_t) buffer[3] ); - position->position.x = FLOAT_FROM_Q11( compactRead >> 21 ) * MAX_PI_COMPACT_POSITION_XY_METERS; - position->position.y = FLOAT_FROM_Q11( ( compactRead >> 10 ) & MASK_11BIT ) * MAX_PI_COMPACT_POSITION_XY_METERS; - position->position.z = FLOAT_FROM_Q10( compactRead & MASK_10BIT ) * MAX_PI_COMPACT_POSITION_Z_METERS; + compactRead = ( (int32_t) buffer[0] << 24 ) | ( (int32_t) buffer[1] << 16 ) | ( (int32_t) buffer[2] << 8 ) | ( (int32_t) buffer[3] ); + position->position.x = FLOAT_FROM_Q10( (int16_t) ( compactRead >> 21 ) ) * MAX_PI_COMPACT_POSITION_XY_METERS; + position->position.y = FLOAT_FROM_Q10( ( (int16_t) ( compactRead >> 10 ) ) & MASK_11BIT ) * MAX_PI_COMPACT_POSITION_XY_METERS; + position->position.z = FLOAT_FROM_Q9( (int16_t) ( compactRead & MASK_10BIT ) ) * MAX_PI_COMPACT_POSITION_Z_METERS; return IVAS_ERR_OK; } @@ -876,9 +876,9 @@ static ivas_error packISMPositionCompact( const IVAS_PIDATA_GENERIC *piData, uin buffer[nBytes++] = (uint8_t) ism_position->numObjects * 4; for ( n = 0; n < ism_position->numObjects; n++ ) { - posX = (uint16_t) ivasPayload_convertToQ11( ism_position->position[n].x / MAX_PI_COMPACT_POSITION_XY_METERS ); - posY = (uint16_t) ivasPayload_convertToQ11( ism_position->position[n].y / MAX_PI_COMPACT_POSITION_XY_METERS ); - posZ = (uint16_t) ivasPayload_convertToQ10( ism_position->position[n].z / MAX_PI_COMPACT_POSITION_Z_METERS ); + posX = (uint16_t) ivasPayload_convertToQ10( ism_position->position[n].x / MAX_PI_COMPACT_POSITION_XY_METERS ); + posY = (uint16_t) ivasPayload_convertToQ10( ism_position->position[n].y / MAX_PI_COMPACT_POSITION_XY_METERS ); + posZ = (uint16_t) ivasPayload_convertToQ9( ism_position->position[n].z / MAX_PI_COMPACT_POSITION_Z_METERS ); buffer[nBytes++] = (uint8_t) ( posX >> 8 ); buffer[nBytes++] = (uint8_t) ( ( ( posX & MASK_3BIT ) << 5 ) | posY >> 6 ); buffer[nBytes++] = (uint8_t) ( ( ( posY & MASK_6BIT ) << 2 ) | posZ >> 8 ); @@ -891,7 +891,7 @@ static ivas_error packISMPositionCompact( const IVAS_PIDATA_GENERIC *piData, uin static ivas_error unpackISMPositionCompact( const uint8_t *buffer, uint32_t numDataBytes, IVAS_PIDATA_GENERIC *piData ) { uint16_t n; - uint32_t compactRead = 0; + int32_t compactRead = 0; IVAS_PIDATA_ISM_POSITION *ism_position = (IVAS_PIDATA_ISM_POSITION *) piData; /* Compact position data is 4 bytes */ @@ -901,15 +901,15 @@ static ivas_error unpackISMPositionCompact( const uint8_t *buffer, uint32_t numD } ism_position->size = sizeof( IVAS_PIDATA_ISM_POSITION ); - ism_position->piDataType = IVAS_PI_ISM_POSITION; + ism_position->piDataType = IVAS_PI_ISM_POSITION_COMPACT; ism_position->numObjects = (uint16_t) numDataBytes / 4; for ( n = 0; n < ism_position->numObjects; n++ ) { - compactRead = ( (uint32_t) buffer[0] << 24 ) | ( (uint32_t) buffer[1] << 16 ) | ( (uint32_t) buffer[2] << 8 ) | ( (uint32_t) buffer[3] ); - ism_position->position[n].x = FLOAT_FROM_Q11( compactRead >> 21 ) * MAX_PI_COMPACT_POSITION_XY_METERS; - ism_position->position[n].y = FLOAT_FROM_Q11( ( compactRead >> 10 ) & MASK_11BIT ) * MAX_PI_COMPACT_POSITION_XY_METERS; - ism_position->position[n].z = FLOAT_FROM_Q10( compactRead & MASK_10BIT ) * MAX_PI_COMPACT_POSITION_Z_METERS; + compactRead = ( (int32_t) buffer[0] << 24 ) | ( (int32_t) buffer[1] << 16 ) | ( (int32_t) buffer[2] << 8 ) | ( (int32_t) buffer[3] ); + ism_position->position[n].x = FLOAT_FROM_Q10( (int16_t) ( compactRead >> 21 ) ) * MAX_PI_COMPACT_POSITION_XY_METERS; + ism_position->position[n].y = FLOAT_FROM_Q10( ( (int16_t) ( compactRead >> 10 ) ) & MASK_11BIT ) * MAX_PI_COMPACT_POSITION_XY_METERS; + ism_position->position[n].z = FLOAT_FROM_Q9( (int16_t) ( compactRead & MASK_10BIT ) ) * MAX_PI_COMPACT_POSITION_Z_METERS; } return IVAS_ERR_OK; } diff --git a/tests/rtp/ivasrtp.py b/tests/rtp/ivasrtp.py index f3d286aa58..d07219ac1d 100644 --- a/tests/rtp/ivasrtp.py +++ b/tests/rtp/ivasrtp.py @@ -730,8 +730,8 @@ cmrLookup = [ ] q15 = lambda x: int(min(32767.0, max(-32768.0, x * 32768.0))) -q11 = lambda x: int(min(2047.0, max(-2048.0, x * 2048.0))) q10 = lambda x: int(min(1023.0, max(-1024.0, x * 1024.0))) +q9 = lambda x: int(min(511.0, max(-512.0, x * 512.0))) q7 = lambda x: int(min(127.0, max(-128.0, x * 128.0))) @@ -822,9 +822,9 @@ def packPositionsCompact(bitstrm: BitStream, data: any): assert ( type(position) == POSITION ), "Compact position PI Data expects a data of type list[POSITIONS]" - bitstrm.append(f"intbe:11={q11(position.x / 20.48)}") - bitstrm.append(f"intbe:11={q11(position.y / 20.48)}") - bitstrm.append(f"intbe:10={q10(position.z / 10.24)}") + bitstrm.append(f"int:11={q10(position.x / 10.24)}") + bitstrm.append(f"int:11={q10(position.y / 10.24)}") + bitstrm.append(f"int:10={q9(position.z / 5.12)}") def unpackOrientation(bitstrm: ConstBitStream, piSize: int) -> ORIENTATION: diff --git a/tests/rtp/test_rtp.py b/tests/rtp/test_rtp.py index bb57259eaa..e9417b3675 100644 --- a/tests/rtp/test_rtp.py +++ b/tests/rtp/test_rtp.py @@ -193,6 +193,11 @@ def generatePiData(startTs: int, endTs: int) -> dict: y=random.randint(-32788, 32767) / 100.0, z=random.randint(-32788, 32767) / 100.0, ) + somePositionCompact = lambda: POSITION( + x=random.randint(-1024, 1023) / 100.0, + y=random.randint(-1024, 1023) / 100.0, + z=random.randint(-512, 511) / 100.0, + ) someDesc = lambda: AUDIO_DESCRIPTION( isSpeech=bool(random.getrandbits(1)), isMusic=bool(random.getrandbits(1)), @@ -275,6 +280,7 @@ def generatePiData(startTs: int, endTs: int) -> dict: someISMGains = lambda num_ism : ISM_GAIN(gains=[random.choice([int(random.randint(-24,12)), -128]) for _ in range(num_ism)]) # -128 corresponds to -Inf someISMOrientations = lambda num_ism : [ORIENTATION(w=2*random.random()-1.0, x=2*random.random()-1.0, y=2*random.random()-1.0, z=2*random.random()-1.0) for _ in range(num_ism)] someISMPositions = lambda num_ism : [POSITION( x=random.randint(-32788, 32767)/100.0, y=random.randint(-32788, 32767)/100.0, z=random.randint(-32788, 32767)/100.0) for _ in range(num_ism)] + someISMPositionsCompact = lambda num_ism : [POSITION( x=random.randint(-1024, 1023)/100.0, y=random.randint(-1024, 1023)/100.0, z=random.randint(-512, 511)/100.0) for _ in range(num_ism)] 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.choice([random.randint(-30,0)*3, -128])) for _ in range(num_ism)] # -128 corresponds to -Inf @@ -301,6 +307,7 @@ def generatePiData(startTs: int, endTs: int) -> dict: pidata["ISM_GAIN"] = someISMGains(pidata["ISM_NUM"].num) pidata["ISM_ORIENTATION"] = someISMOrientations(pidata["ISM_NUM"].num) pidata["ISM_POSITION"] = someISMPositions(pidata["ISM_NUM"].num) + pidata["ISM_POSITION_COMPACT"] = someISMPositionsCompact(pidata["ISM_NUM"].num) pidata["ISM_DISTANCE_ATTENUATION"] = someISMDistanceAttenuations(pidata["ISM_NUM"].num) pidata["ISM_DIRECTIVITY"] = someISMDirectivities(pidata["ISM_NUM"].num) @@ -308,6 +315,7 @@ def generatePiData(startTs: int, endTs: int) -> dict: pidata["R_ISM_GAIN"] = someReverseISMGain() pidata["R_ISM_ORIENTATION"] = someOrientation() pidata["R_ISM_POSITION"] = somePosition() + pidata["R_ISM_POSITION_COMPACT"] = somePositionCompact() pidata["R_ISM_DIRECTION"] = someReverseISMDirection() data[str(ts)] = pidata return data -- GitLab From b722441236bb25ddb0267ef1d5083f832342b49c Mon Sep 17 00:00:00 2001 From: Lauros Pajunen Date: Wed, 19 Nov 2025 12:50:02 -0600 Subject: [PATCH 06/24] Fix usan, orientation progreses --- lib_util/ivas_rtp_pi_data.c | 12 ++++++++++-- tests/rtp/ivasrtp.py | 21 ++++++++++++++++++--- tests/rtp/test_rtp.py | 19 +++++++++++++++---- 3 files changed, 43 insertions(+), 9 deletions(-) diff --git a/lib_util/ivas_rtp_pi_data.c b/lib_util/ivas_rtp_pi_data.c index 0590232110..779e3fabb8 100644 --- a/lib_util/ivas_rtp_pi_data.c +++ b/lib_util/ivas_rtp_pi_data.c @@ -111,12 +111,12 @@ static int16_t ivasPayload_convertToQ9( float value ) * * Convert a float value into a Q7 encoded value. *-----------------------------------------------------------------------*/ -static int8_t ivasPayload_convertToQ7( float value ) +static int16_t ivasPayload_convertToQ7( float value ) { value = ( value * 128.0f ); value = value > +128.0f ? +128.0f : value; value = value < -128.0f ? -128.0f : value; - return (int8_t) ( value ); + return (int16_t) ( value ); } #endif @@ -775,6 +775,14 @@ static ivas_error unpackPositionCompact( const uint8_t *buffer, uint32_t numData return IVAS_ERROR( IVAS_ERR_RTP_UNPACK_PI_DATA, "Incorrect size to unpack compact position PI data" ); } + int16_t value1 = -100; + int16_t value2 = 100; + uint16_t value1_uint16 = (uint16_t) value1; + uint16_t value2_uint16 = (uint16_t) value2; + + + + position->size = sizeof( IVAS_PIDATA_POSITION ); compactRead = ( (int32_t) buffer[0] << 24 ) | ( (int32_t) buffer[1] << 16 ) | ( (int32_t) buffer[2] << 8 ) | ( (int32_t) buffer[3] ); diff --git a/tests/rtp/ivasrtp.py b/tests/rtp/ivasrtp.py index d07219ac1d..9129616e87 100644 --- a/tests/rtp/ivasrtp.py +++ b/tests/rtp/ivasrtp.py @@ -43,6 +43,8 @@ import base64 import argparse from pathlib import Path from typing import cast, Optional +import numpy as np +import ctypes NO_REQ = "NO_REQ" @@ -657,6 +659,8 @@ 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)] +MASK_3BIT = 0x7 +MASK_6BIT = 0x3F def mapNearestIndex(table: list, val: float) -> int: for idx, entry in enumerate(table): @@ -822,9 +826,20 @@ def packPositionsCompact(bitstrm: BitStream, data: any): assert ( type(position) == POSITION ), "Compact position PI Data expects a data of type list[POSITIONS]" - bitstrm.append(f"int:11={q10(position.x / 10.24)}") - bitstrm.append(f"int:11={q10(position.y / 10.24)}") - bitstrm.append(f"int:10={q9(position.z / 5.12)}") + #posX = np.uint16(q10(position.x / 10.24)) + #posY = np.uint16(q10(position.y / 10.24)) + #posZ = np.uint16(q9(position.z / 5.12)) + posX = ctypes.c_int16( q10(position.x / 10.24) ).value + posY = ctypes.c_int16( q10(position.y / 10.24) ).value + posZ = ctypes.c_int16( q9(position.z / 5.12) ).value + bitstrm.append(f"uintbe:8={ctypes.c_uint8(posX >> 3).value}") + bitstrm.append(f"uintbe:8={ctypes.c_uint8(( (posX & MASK_3BIT) << 5 ) | (posY >> 6)).value}") + bitstrm.append(f"uintbe:8={ctypes.c_uint8(( (posY & MASK_6BIT) << 2 ) | (posZ >> 8)).value}") + bitstrm.append(f"uintbe:8={(posZ >> 2)}") + + #bitstrm.append(f"int:11={q10(position.x / 10.24)}") + #bitstrm.append(f"int:11={q10(position.y / 10.24)}") + #bitstrm.append(f"int:10={q9(position.z / 5.12)}") def unpackOrientation(bitstrm: ConstBitStream, piSize: int) -> ORIENTATION: diff --git a/tests/rtp/test_rtp.py b/tests/rtp/test_rtp.py index e9417b3675..8eea91c8ee 100644 --- a/tests/rtp/test_rtp.py +++ b/tests/rtp/test_rtp.py @@ -193,10 +193,15 @@ def generatePiData(startTs: int, endTs: int) -> dict: y=random.randint(-32788, 32767) / 100.0, z=random.randint(-32788, 32767) / 100.0, ) + #somePositionCompact = lambda: POSITION( + # x=random.randint(-1024, 1023) / 100.0, + # y=random.randint(-1024, 1023) / 100.0, + # z=random.randint(-512, 511) / 100.0, + #) somePositionCompact = lambda: POSITION( - x=random.randint(-1024, 1023) / 100.0, - y=random.randint(-1024, 1023) / 100.0, - z=random.randint(-512, 511) / 100.0, + x=1.0, + y=1.0, + z=-1.0, ) someDesc = lambda: AUDIO_DESCRIPTION( isSpeech=bool(random.getrandbits(1)), @@ -290,6 +295,11 @@ def generatePiData(startTs: int, endTs: int) -> dict: for ts in range(startTs, endTs, 320): pidata = dict() + + pidata["ISM_NUM"] = someNumISM() + pidata["ISM_POSITION_COMPACT"] = someISMPositionsCompact(pidata["ISM_NUM"].num) + #pidata["R_ISM_POSITION_COMPACT"] = somePositionCompact() + ''' pidata["SCENE_ORIENTATION"] = someOrientation() pidata["DEVICE_ORIENTATION_COMPENSATED"] = someOrientation() pidata["DEVICE_ORIENTATION_UNCOMPENSATED"] = someOrientation() @@ -317,6 +327,7 @@ def generatePiData(startTs: int, endTs: int) -> dict: pidata["R_ISM_POSITION"] = somePosition() pidata["R_ISM_POSITION_COMPACT"] = somePositionCompact() pidata["R_ISM_DIRECTION"] = someReverseISMDirection() + ''' data[str(ts)] = pidata return data @@ -758,7 +769,7 @@ def run_rtp_bitstream_tests( elif pitype == "ISM_ORIENTATION": for r, d in zip(generatedPIData[ts][pitype], decodedPiData[ts][pitype]): isEqualOrientation(ORIENTATION(**d), r) - elif pitype == "ISM_POSITION": + elif pitype == "ISM_POSITION" or pitype == "ISM_POSITION_COMPACT": for r, d in zip(generatedPIData[ts][pitype], decodedPiData[ts][pitype]): isEqualPosition(POSITION(**d), r) elif pitype == "ISM_DISTANCE_ATTENUATION": -- GitLab From 058ada59ba2ce9d40f04fbf29dc0f5d1ef042322 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20Toftg=C3=A5rd?= Date: Wed, 19 Nov 2025 21:11:53 +0100 Subject: [PATCH 07/24] Updated representation for quaternions for PI data --- lib_com/options.h | 1 + lib_util/ivas_rtp_internal.h | 3 + lib_util/ivas_rtp_pi_data.c | 144 ++++++++++++++++++++++++++++++----- tests/rtp/ivasrtp.py | 44 +++++++---- tests/rtp/test_rtp.py | 54 ++++++------- 5 files changed, 182 insertions(+), 64 deletions(-) diff --git a/lib_com/options.h b/lib_com/options.h index 7aa9f1c915..a71ccde078 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -169,6 +169,7 @@ #define DECODER_FORMAT_SWITCHING /* Re-initialize the decoder when the format/subformat of the incoming stream is changed */ #define RTP_SR_CODEC_FRAME_SIZE_IN_TOC_BYTE /* CR for split rendering codec framesize signalling in Toc Byte*/ #define FIX_SPLIT_RENDERING_ON_DECODER_RESTART /* Re-configure split rendering on decoder restart */ +#define COMPACT_ORIENTATION_PI_DATA /* ################### Start BE switches ################################# */ /* only BE switches wrt selection floating point code */ diff --git a/lib_util/ivas_rtp_internal.h b/lib_util/ivas_rtp_internal.h index a550892548..ad89cdb6d8 100644 --- a/lib_util/ivas_rtp_internal.h +++ b/lib_util/ivas_rtp_internal.h @@ -51,6 +51,9 @@ enum MASK_BITS #ifdef REVERSE_ISM_PI_DATA MASK_9BIT = 0x1FF, #endif +#ifdef COMPACT_ORIENTATION_PI_DATA + MASK_10BIT = 0x3FF, +#endif }; diff --git a/lib_util/ivas_rtp_pi_data.c b/lib_util/ivas_rtp_pi_data.c index b9b7bcc7e4..0a0899790b 100644 --- a/lib_util/ivas_rtp_pi_data.c +++ b/lib_util/ivas_rtp_pi_data.c @@ -37,6 +37,9 @@ #endif #ifdef ISM_PI_DATA #include +#ifdef COMPACT_ORIENTATION_PI_DATA +#include "tools.c" +#endif #ifndef min #define min( x, y ) ( ( x ) < ( y ) ? ( x ) : ( y ) ) @@ -79,6 +82,85 @@ static int16_t ivasPayload_convertToQ15( float value ) return (int16_t) ( value ); } +#ifdef COMPACT_ORIENTATION_PI_DATA +static uint32_t packQuaternion( IVAS_QUATERNION orientation, uint8_t *buffer ) +{ + uint32_t nBytes = 0; + float q[4], q_max; + uint16_t max_q_idx, n, k; + uint32_t lWord; + + q[0] = orientation.w; + q[1] = orientation.x; + q[2] = orientation.y; + q[3] = orientation.z; + + max_q_idx = maximumAbs( q, 4, &q_max ); + if ( q[max_q_idx] < 0 ) + { + for ( n = 0; n < 4; n++ ) + { + q[n] = -q[n]; + } + } + lWord = max_q_idx << 30; + + k = 1; + for ( n = 0; n < 4; n++ ) + { + if ( n == max_q_idx ) + { + continue; + } + lWord |= ( ( (int16_t) ( ( q[n] + 1 ) * 1023 * 0.5f ) & MASK_10BIT ) << ( 30 - k * 10 ) ); + k++; + } + + buffer[nBytes++] = ( lWord >> 24 ) & MASK_8BIT; + buffer[nBytes++] = ( lWord >> 16 ) & MASK_8BIT; + buffer[nBytes++] = ( lWord >> 8 ) & MASK_8BIT; + buffer[nBytes++] = (lWord) &MASK_8BIT; + + return nBytes; +} + + +static ivas_error unpackQuaternion( const uint8_t *buffer, IVAS_QUATERNION *orientation ) +{ + uint32_t i, k, lWord; + uint16_t max_q_idx, tmp; + float q[4], qs; + + lWord = ( buffer[0] ) << 24; + lWord |= ( buffer[1] ) << 16; + lWord |= ( buffer[2] ) << 8; + lWord |= buffer[3]; + + max_q_idx = ( lWord >> 30 ) & MASK_2BIT; + k = 1; + qs = 0.0f; + for ( i = 0; i < 4; i++ ) + { + if ( i == max_q_idx ) + { + continue; + } + tmp = ( lWord >> ( 30 - k * 10 ) ) & MASK_10BIT; + q[i] = tmp / 1023.0f * 2.0f - 1; + qs += q[i] * q[i]; + k++; + } + q[max_q_idx] = sqrtf( 1 - qs ); + orientation->w = q[0]; + orientation->x = q[1]; + orientation->y = q[2]; + orientation->z = q[3]; + + return IVAS_ERR_OK; +} + +#endif + static ivas_error packUnsupportedData( const IVAS_PIDATA_GENERIC *piData, uint8_t *buffer, uint32_t maxDataBytes, uint32_t *nBytesWritten ) { (void) piData; @@ -152,19 +234,22 @@ static ivas_error packOrientation( const IVAS_PIDATA_GENERIC *piData, uint8_t *b return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect PI ID in Orientation PI data" ); } - /* Orientation data is 8 bytes, header is 2 bytes */ - if ( maxDataBytes < 8 + 2 ) + /* Orientation data is 4 bytes, header is 2 bytes */ + if ( maxDataBytes < 4 + 2 ) { return IVAS_ERROR( IVAS_ERR_RTP_INSUFFICIENT_OUTPUT_SIZE, "Insufficient space to pack Orientation PI data" ); } buffer[nBytes++] = ( orientation->piDataType & MASK_5BIT ); /* PF/PM populated during final packing */ - buffer[nBytes++] = 8; + buffer[nBytes++] = 4; +#ifdef COMPACT_ORIENTATION_PI_DATA + nBytes += packQuaternion( orientation->orientation, &buffer[nBytes] ); +#else nBytes = writeInt16( buffer, nBytes, ivasPayload_convertToQ15( orientation->orientation.w ) ); nBytes = writeInt16( buffer, nBytes, ivasPayload_convertToQ15( orientation->orientation.x ) ); nBytes = writeInt16( buffer, nBytes, ivasPayload_convertToQ15( orientation->orientation.y ) ); nBytes = writeInt16( buffer, nBytes, ivasPayload_convertToQ15( orientation->orientation.z ) ); - +#endif *nBytesWritten = nBytes; return IVAS_ERR_OK; } @@ -196,10 +281,14 @@ static ivas_error packISMOrientation( const IVAS_PIDATA_GENERIC *piData, uint8_t buffer[nBytes++] = (uint8_t) orientation->numObjects * 8; for ( n = 0; n < orientation->numObjects; n++ ) { +#ifdef COMPACT_ORIENTATION_PI_DATA + nBytes += packQuaternion( orientation->orientation[n], &buffer[nBytes] ); +#else nBytes = writeInt16( buffer, nBytes, ivasPayload_convertToQ15( orientation->orientation[n].w ) ); nBytes = writeInt16( buffer, nBytes, ivasPayload_convertToQ15( orientation->orientation[n].x ) ); nBytes = writeInt16( buffer, nBytes, ivasPayload_convertToQ15( orientation->orientation[n].y ) ); nBytes = writeInt16( buffer, nBytes, ivasPayload_convertToQ15( orientation->orientation[n].z ) ); +#endif } *nBytesWritten = nBytes; return IVAS_ERR_OK; @@ -210,17 +299,21 @@ static ivas_error unpackOrientation( const uint8_t *buffer, uint32_t numDataByte { IVAS_PIDATA_ORIENTATION *orientation = (IVAS_PIDATA_ORIENTATION *) piData; - /* Orientation data is 8 bytes */ - if ( numDataBytes != 8 ) + /* Orientation data is 4 bytes */ + if ( numDataBytes != 4 ) { return IVAS_ERROR( IVAS_ERR_RTP_UNPACK_PI_DATA, "Incorrect size to unpack Orientation PI data" ); } piData->size = sizeof( IVAS_PIDATA_ORIENTATION ); +#ifdef COMPACT_ORIENTATION_PI_DATA + unpackQuaternion( buffer, &( orientation->orientation ) ); +#else orientation->orientation.w = FLOAT_FROM_Q15( readInt16( &buffer[0] ) ); orientation->orientation.x = FLOAT_FROM_Q15( readInt16( &buffer[2] ) ); orientation->orientation.y = FLOAT_FROM_Q15( readInt16( &buffer[4] ) ); orientation->orientation.z = FLOAT_FROM_Q15( readInt16( &buffer[6] ) ); +#endif return IVAS_ERR_OK; } @@ -230,22 +323,26 @@ static ivas_error unpackISMOrientation( const uint8_t *buffer, uint32_t numDataB { IVAS_PIDATA_ISM_ORIENTATION *ism_orientation = (IVAS_PIDATA_ISM_ORIENTATION *) piData; - /* Orientation data is 8 bytes */ + /* Orientation data is 4 bytes */ uint16_t n; - if ( numDataBytes % 8 != 0 ) + if ( numDataBytes % 4 != 0 ) { return IVAS_ERROR( IVAS_ERR_RTP_UNPACK_PI_DATA, "Incorrect size to unpack Orientation PI data" ); } ism_orientation->size = sizeof( IVAS_PIDATA_ISM_ORIENTATION ); - ism_orientation->numObjects = (uint16_t) numDataBytes / 8; + ism_orientation->numObjects = (uint16_t) numDataBytes / 4; for ( n = 0; n < ism_orientation->numObjects; n++ ) { +#ifdef COMPACT_ORIENTATION_PI_DATA + unpackQuaternion( &buffer[4 * n], &( ism_orientation->orientation[n] ) ); +#else ism_orientation->orientation[n].w = FLOAT_FROM_Q15( readInt16( &buffer[8 * n] ) ); ism_orientation->orientation[n].x = FLOAT_FROM_Q15( readInt16( &buffer[8 * n + 2] ) ); ism_orientation->orientation[n].y = FLOAT_FROM_Q15( readInt16( &buffer[8 * n + 4] ) ); ism_orientation->orientation[n].z = FLOAT_FROM_Q15( readInt16( &buffer[8 * n + 6] ) ); +#endif } for ( ; n < IVAS_MAX_NUM_OBJECTS; n++ ) { @@ -754,11 +851,11 @@ static ivas_error packAudioFocusCommon( const IVAS_PIDATA_GENERIC *piData, uint8 if ( audioFocus->availDirection && audioFocus->availLevel ) { - packedSize = 9; + packedSize = 5; } else if ( audioFocus->availDirection ) { - packedSize = 8; + packedSize = 4; } else if ( audioFocus->availLevel ) { @@ -778,14 +875,19 @@ static ivas_error packAudioFocusCommon( const IVAS_PIDATA_GENERIC *piData, uint8 buffer[nBytes++] = ( audioFocus->piDataType & MASK_5BIT ); /* PF/PM populated during final packing */ buffer[nBytes++] = packedSize; - if ( packedSize == 9 || packedSize == 8 ) + if ( packedSize == 5 || packedSize == 4 ) { +#ifdef COMPACT_ORIENTATION_PI_DATA + nBytes += packQuaternion( audioFocus->direction, &buffer[nBytes] ); +#else + nBytes = writeInt16( buffer, nBytes, ivasPayload_convertToQ15( audioFocus->direction.w ) ); nBytes = writeInt16( buffer, nBytes, ivasPayload_convertToQ15( audioFocus->direction.x ) ); nBytes = writeInt16( buffer, nBytes, ivasPayload_convertToQ15( audioFocus->direction.y ) ); nBytes = writeInt16( buffer, nBytes, ivasPayload_convertToQ15( audioFocus->direction.z ) ); +#endif } - if ( packedSize == 9 || packedSize == 1 ) + if ( packedSize == 5 || packedSize == 1 ) { buffer[nBytes++] = ( (uint8_t) audioFocus->flvl & MASK_4BIT ) << 4; } @@ -798,15 +900,15 @@ static ivas_error unpackAudioFocusCommon( const uint8_t *buffer, uint32_t numDat { IVAS_PIDATA_AUDIO_FOCUS *audioFocus = (IVAS_PIDATA_AUDIO_FOCUS *) piData; - /* Audio Focus data is either 1, 8 or 9 bytes */ - if ( numDataBytes != 1 && numDataBytes != 8 && numDataBytes != 9 ) + /* Audio Focus data is either 1, 4 or 5 bytes */ + if ( numDataBytes != 1 && numDataBytes != 4 && numDataBytes != 5 ) { return IVAS_ERROR( IVAS_ERR_RTP_UNPACK_PI_DATA, "Incorrect size to unpack PI data of type Audio Focus" ); } piData->size = sizeof( IVAS_PIDATA_AUDIO_FOCUS ); - audioFocus->availDirection = ( numDataBytes >= 8 ); - audioFocus->availLevel = ( numDataBytes == 1 || numDataBytes == 9 ); + audioFocus->availDirection = ( numDataBytes >= 4 ); + audioFocus->availLevel = ( numDataBytes == 1 || numDataBytes == 5 ); if ( numDataBytes == 1 ) { @@ -814,14 +916,18 @@ static ivas_error unpackAudioFocusCommon( const uint8_t *buffer, uint32_t numDat } else { +#ifdef COMPACT_ORIENTATION_PI_DATA + unpackQuaternion( buffer, &( audioFocus->direction ) ); +#else audioFocus->direction.w = FLOAT_FROM_Q15( readInt16( &buffer[0] ) ); audioFocus->direction.x = FLOAT_FROM_Q15( readInt16( &buffer[2] ) ); audioFocus->direction.y = FLOAT_FROM_Q15( readInt16( &buffer[4] ) ); audioFocus->direction.z = FLOAT_FROM_Q15( readInt16( &buffer[6] ) ); +#endif - if ( numDataBytes == 9 ) + if ( numDataBytes == 5 ) { - audioFocus->flvl = ( buffer[8] >> 4 ); + audioFocus->flvl = ( buffer[4] >> 4 ); } } diff --git a/tests/rtp/ivasrtp.py b/tests/rtp/ivasrtp.py index 5b1bb2be79..34305dc9a5 100644 --- a/tests/rtp/ivasrtp.py +++ b/tests/rtp/ivasrtp.py @@ -748,16 +748,28 @@ def packNoPiData(bitstrm: BitStream, data: any = None): def unpackOrientations(bitstrm: ConstBitStream, piSize: int) -> list[ORIENTATION]: assert ( - piSize % 8 + piSize % 4 ) == 0 and piSize <= 32, "Incorrect PI Data Size for list[ORIENTATION]" orientations = list() + q = [(float)]*4 + qs = 0 while piSize > 0: - w = bitstrm.read(16).int / 32768.0 - x = bitstrm.read(16).int / 32768.0 - y = bitstrm.read(16).int / 32768.0 - z = bitstrm.read(16).int / 32768.0 + max_q_idx = bitstrm.read(2).uint + for i in range(0,4): + if i == max_q_idx: + continue + tmp = bitstrm.read(10).uint + q[i] = (tmp / 1023.0) * 2.0 - 1.0 + qs = qs + q[i]**2 + + q[max_q_idx] = (1 - qs)**0.5 + + w = q[0] + x = q[1] + y = q[2] + z = q[3] orientations.append(ORIENTATION(w, x, y, z)) - piSize -= 8 + piSize -= 4 return orientations @@ -767,10 +779,16 @@ def packOrientations(bitstrm: BitStream, data: any): assert ( type(orientation) == ORIENTATION ), "Orientation PI Data expects a data of type list[ORIENTATION]" - bitstrm.append(f"intbe:16={q15(orientation.w)}") - bitstrm.append(f"intbe:16={q15(orientation.x)}") - bitstrm.append(f"intbe:16={q15(orientation.y)}") - bitstrm.append(f"intbe:16={q15(orientation.z)}") + q = [orientation.w, orientation.x, orientation.y, orientation.z] + max_q = max(q, key=abs) + max_q_idx = q.index(max_q) + if max_q < 0: + q = [-x for x in q] + bitstrm.append(f"uint:2={max_q_idx}") + for i in range(0,4): + if i == max_q_idx: + continue + bitstrm.append(f"uint:10={(int)((q[i]+1)*1023*1/2)}") def unpackPositions(bitstrm: ConstBitStream, piSize: int) -> list[POSITION]: @@ -799,7 +817,7 @@ def packPositions(bitstrm: BitStream, data: any): def unpackOrientation(bitstrm: ConstBitStream, piSize: int) -> ORIENTATION: - assert piSize == 8, "Incorrect PI Data Size for ORIENTATION" + assert piSize == 4, "Incorrect PI Data Size for ORIENTATION" orientations = unpackOrientations(bitstrm, piSize) assert len(orientations) == 1 return orientations[0] @@ -983,8 +1001,8 @@ def unpackAudioFocus(bitstrm: ConstBitStream, piSize: int) -> AUDIO_FOCUS: level = bitstrm.read(4).uint _ = bitstrm.read(4) else: - direction = unpackOrientation(bitstrm, 8) - if piSize == 9: + direction = unpackOrientation(bitstrm, 4) + if piSize == 5: level = bitstrm.read(4).uint _ = bitstrm.read(4) diff --git a/tests/rtp/test_rtp.py b/tests/rtp/test_rtp.py index 53cb6488c5..980c5ba820 100644 --- a/tests/rtp/test_rtp.py +++ b/tests/rtp/test_rtp.py @@ -182,12 +182,17 @@ def generateRequests(startTs: int, endTs: int) -> dict: def generatePiData(startTs: int, endTs: int) -> dict: data = dict() - someOrientation = lambda: ORIENTATION( - w=2 * random.random() - 1.0, - x=2 * random.random() - 1.0, - y=2 * random.random() - 1.0, - z=2 * random.random() - 1.0, - ) + def random_unit_quaternion(): + w = 2*random.random() - 1.0 + x = 2*random.random() - 1.0 + y = 2*random.random() - 1.0 + z = 2*random.random() - 1.0 + n = (w*w + x*x + y*y + z*z)**0.5 + if n == 0.0: + return random_unit_quaternion() + return ORIENTATION(w/n, x/n, y/n, z/n) + + someOrientation = lambda: random_unit_quaternion() somePosition = lambda: POSITION( x=random.randint(-32788, 32767) / 100.0, y=random.randint(-32788, 32767) / 100.0, @@ -209,23 +214,8 @@ def generatePiData(startTs: int, endTs: int) -> dict: someDIG = lambda: DIEGETIC_TYPE( isDigetic=[bool(random.getrandbits(1)) for _ in range(random.randint(1, 5))] ) - someAuFocusDirLvl = lambda: AUDIO_FOCUS( - ORIENTATION( - w=2 * random.random() - 1.0, - x=2 * random.random() - 1.0, - y=2 * random.random() - 1.0, - z=2 * random.random() - 1.0, - ), - level=AUDIO_FOCUS_LEVEL(random.randint(0, 15)), - ) - someAuFocusDir = lambda: AUDIO_FOCUS( - ORIENTATION( - w=2 * random.random() - 1.0, - x=2 * random.random() - 1.0, - y=2 * random.random() - 1.0, - z=2 * random.random() - 1.0, - ) - ) + someAuFocusDirLvl = lambda: AUDIO_FOCUS(random_unit_quaternion(),level=AUDIO_FOCUS_LEVEL(random.randint(0, 15)),) + someAuFocusDir = lambda: AUDIO_FOCUS(random_unit_quaternion()) someAuFocusLvl = lambda: AUDIO_FOCUS(level=AUDIO_FOCUS_LEVEL(random.randint(0, 15))) someAuFocusList = [someAuFocusDirLvl, someAuFocusDir, someAuFocusLvl] someLatency = lambda: PI_LATENCY( @@ -273,7 +263,7 @@ def generatePiData(startTs: int, endTs: int) -> dict: someNumISM = lambda : ISM_NUM(num=random.randint(1, 4)) someISMIds = lambda num_ism : ISM_ID(ids=[int(random.getrandbits(8)) for _ in range(num_ism)]) someISMGains = lambda num_ism : ISM_GAIN(gains=[random.choice([int(random.randint(-24,12)), -128]) for _ in range(num_ism)]) # -128 corresponds to -Inf - someISMOrientations = lambda num_ism : [ORIENTATION(w=2*random.random()-1.0, x=2*random.random()-1.0, y=2*random.random()-1.0, z=2*random.random()-1.0) for _ in range(num_ism)] + someISMOrientations = lambda num_ism : [random_unit_quaternion() for _ in range(num_ism)] someISMPositions = lambda num_ism : [POSITION( x=random.randint(-32788, 32767)/100.0, y=random.randint(-32788, 32767)/100.0, z=random.randint(-32788, 32767)/100.0) for _ in range(num_ism)] 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.choice([random.randint(-30,0)*3, -128])) for _ in range(num_ism)] # -128 corresponds to -Inf @@ -322,10 +312,10 @@ def isEqualFrame(refFrame: bytes, dutFrame: bytes): def isEqualOrientation(ref: ORIENTATION, dut: ORIENTATION): - assert abs(ref.w - dut.w) < 0.0001, "Scene Orientation PI Data mismatch in w" - assert abs(ref.x - dut.x) < 0.0001, "Scene Orientation PI Data mismatch in x" - assert abs(ref.y - dut.y) < 0.0001, "Scene Orientation PI Data mismatch in y" - assert abs(ref.z - dut.z) < 0.0001, "Scene Orientation PI Data mismatch in z" + assert abs(abs(ref.w) - abs(dut.w)) < 0.01, "Scene Orientation PI Data mismatch in w" + assert abs(abs(ref.x) - abs(dut.x)) < 0.01, "Scene Orientation PI Data mismatch in x" + assert abs(abs(ref.y) - abs(dut.y)) < 0.01, "Scene Orientation PI Data mismatch in y" + assert abs(abs(ref.z) - abs(dut.z)) < 0.01, "Scene Orientation PI Data mismatch in z" def isEqualPosition(ref: POSITION, dut: POSITION): @@ -392,16 +382,16 @@ def isEqualAudioFocus(ref: AUDIO_FOCUS, dut: AUDIO_FOCUS): assert dut.direction is not None, "Audio Focus PI Data missing direction" if ref.direction is not None and dut.direction is not None: assert ( - abs(ref.direction["w"] - dut.direction.w) < 0.0001 + abs(abs(ref.direction["w"]) - abs(dut.direction.w)) < 0.01 ), "Audio Focus PI Data mismatch in direction w" assert ( - abs(ref.direction["x"] - dut.direction.x) < 0.0001 + abs(abs(ref.direction["x"]) - abs(dut.direction.x)) < 0.01 ), "Audio Focus PI Data mismatch in direction x" assert ( - abs(ref.direction["y"] - dut.direction.y) < 0.0001 + abs(abs(ref.direction["y"]) - abs(dut.direction.y)) < 0.01 ), "Audio Focus PI Data mismatch in direction y" assert ( - abs(ref.direction["z"] - dut.direction.z) < 0.0001 + abs(abs(ref.direction["z"]) - abs(dut.direction.z)) < 0.01 ), "Audio Focus PI Data mismatch in direction z" assert ref.level == dut.level, "Audio Focus PI Data mismatch in level" -- GitLab From 3370c478eb2d02a2218550ed4e2496ab0b801a87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20Toftg=C3=A5rd?= Date: Wed, 19 Nov 2025 21:47:50 +0100 Subject: [PATCH 08/24] add missing endif --- lib_util/ivas_rtp_pi_data.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_util/ivas_rtp_pi_data.c b/lib_util/ivas_rtp_pi_data.c index 54cdd1a967..53e59ebe99 100644 --- a/lib_util/ivas_rtp_pi_data.c +++ b/lib_util/ivas_rtp_pi_data.c @@ -405,7 +405,7 @@ static ivas_error unpackOrientation( const uint8_t *buffer, uint32_t numDataByte orientation->orientation.x = FLOAT_FROM_Q15( readInt16( &buffer[2] ) ); orientation->orientation.y = FLOAT_FROM_Q15( readInt16( &buffer[4] ) ); orientation->orientation.z = FLOAT_FROM_Q15( readInt16( &buffer[6] ) ); - +#endif return IVAS_ERR_OK; } -- GitLab From 099ce9c2dcbd3f3129becc8edbcd1a53f07bea45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20Toftg=C3=A5rd?= Date: Wed, 19 Nov 2025 21:53:54 +0100 Subject: [PATCH 09/24] disable unused code --- lib_util/ivas_rtp_pi_data.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib_util/ivas_rtp_pi_data.c b/lib_util/ivas_rtp_pi_data.c index 53e59ebe99..e22b3e58de 100644 --- a/lib_util/ivas_rtp_pi_data.c +++ b/lib_util/ivas_rtp_pi_data.c @@ -873,10 +873,10 @@ static ivas_error unpackPositionCompact( const uint8_t *buffer, uint32_t numData return IVAS_ERROR( IVAS_ERR_RTP_UNPACK_PI_DATA, "Incorrect size to unpack compact position PI data" ); } - int16_t value1 = -100; - int16_t value2 = 100; - uint16_t value1_uint16 = (uint16_t) value1; - uint16_t value2_uint16 = (uint16_t) value2; + //int16_t value1 = -100; + //int16_t value2 = 100; + //uint16_t value1_uint16 = (uint16_t) value1; + //uint16_t value2_uint16 = (uint16_t) value2; -- GitLab From b22714ae162e639afe75bb8d5c0e1c70177a81fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20Toftg=C3=A5rd?= Date: Wed, 19 Nov 2025 21:58:38 +0100 Subject: [PATCH 10/24] remove unused function --- lib_util/ivas_rtp_pi_data.c | 39 ++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/lib_util/ivas_rtp_pi_data.c b/lib_util/ivas_rtp_pi_data.c index e22b3e58de..57dffbd369 100644 --- a/lib_util/ivas_rtp_pi_data.c +++ b/lib_util/ivas_rtp_pi_data.c @@ -109,20 +109,6 @@ static int16_t ivasPayload_convertToQ9( float value ) return (int16_t) ( value ); } -/*-----------------------------------------------------------------------* - * ivasPayload_convertToQ7() - * - * Convert a float value into a Q7 encoded value. - *-----------------------------------------------------------------------*/ -static int16_t ivasPayload_convertToQ7( float value ) -{ - value = ( value * 128.0f ); - value = value > +128.0f ? +128.0f : value; - value = value < -128.0f ? -128.0f : value; - return (int16_t) ( value ); -} -#endif - #ifdef COMPACT_ORIENTATION_PI_DATA static uint32_t packQuaternion( IVAS_QUATERNION orientation, uint8_t *buffer ) { @@ -200,6 +186,21 @@ static ivas_error unpackQuaternion( const uint8_t *buffer, IVAS_QUATERNION *orie return IVAS_ERR_OK; } +#else + +/*-----------------------------------------------------------------------* + * ivasPayload_convertToQ7() + * + * Convert a float value into a Q7 encoded value. + *-----------------------------------------------------------------------*/ +static int16_t ivasPayload_convertToQ7( float value ) +{ + value = ( value * 128.0f ); + value = value > +128.0f ? +128.0f : value; + value = value < -128.0f ? -128.0f : value; + return (int16_t) ( value ); +} +#endif #endif static ivas_error packUnsupportedData( const IVAS_PIDATA_GENERIC *piData, uint8_t *buffer, uint32_t maxDataBytes, uint32_t *nBytesWritten ) @@ -873,12 +874,10 @@ static ivas_error unpackPositionCompact( const uint8_t *buffer, uint32_t numData return IVAS_ERROR( IVAS_ERR_RTP_UNPACK_PI_DATA, "Incorrect size to unpack compact position PI data" ); } - //int16_t value1 = -100; - //int16_t value2 = 100; - //uint16_t value1_uint16 = (uint16_t) value1; - //uint16_t value2_uint16 = (uint16_t) value2; - - + // int16_t value1 = -100; + // int16_t value2 = 100; + // uint16_t value1_uint16 = (uint16_t) value1; + // uint16_t value2_uint16 = (uint16_t) value2; position->size = sizeof( IVAS_PIDATA_POSITION ); -- GitLab From 406aed598903c98023f778933ebd414d8dee963a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20Toftg=C3=A5rd?= Date: Wed, 19 Nov 2025 22:07:51 +0100 Subject: [PATCH 11/24] correct bit mask for 10 and 11 bits --- lib_util/ivas_rtp_internal.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib_util/ivas_rtp_internal.h b/lib_util/ivas_rtp_internal.h index 007730217a..2ab816fab7 100644 --- a/lib_util/ivas_rtp_internal.h +++ b/lib_util/ivas_rtp_internal.h @@ -52,8 +52,8 @@ enum MASK_BITS MASK_9BIT = 0x1FF, #endif #ifdef RTP_UPDATES_SA4_134 - MASK_10BIT = 0x2FF, - MASK_11BIT = 0x3FF, + MASK_10BIT = 0x3FF, + MASK_11BIT = 0x7FF, #endif }; -- GitLab From 2059fef974183eeeaeb36c510a0308ea93eb6121 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20Toftg=C3=A5rd?= Date: Wed, 19 Nov 2025 22:29:05 +0100 Subject: [PATCH 12/24] update packPositionsCompact() --- tests/rtp/ivasrtp.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/rtp/ivasrtp.py b/tests/rtp/ivasrtp.py index 9129616e87..aec9d4cbe3 100644 --- a/tests/rtp/ivasrtp.py +++ b/tests/rtp/ivasrtp.py @@ -829,17 +829,17 @@ def packPositionsCompact(bitstrm: BitStream, data: any): #posX = np.uint16(q10(position.x / 10.24)) #posY = np.uint16(q10(position.y / 10.24)) #posZ = np.uint16(q9(position.z / 5.12)) - posX = ctypes.c_int16( q10(position.x / 10.24) ).value - posY = ctypes.c_int16( q10(position.y / 10.24) ).value - posZ = ctypes.c_int16( q9(position.z / 5.12) ).value - bitstrm.append(f"uintbe:8={ctypes.c_uint8(posX >> 3).value}") - bitstrm.append(f"uintbe:8={ctypes.c_uint8(( (posX & MASK_3BIT) << 5 ) | (posY >> 6)).value}") - bitstrm.append(f"uintbe:8={ctypes.c_uint8(( (posY & MASK_6BIT) << 2 ) | (posZ >> 8)).value}") - bitstrm.append(f"uintbe:8={(posZ >> 2)}") - - #bitstrm.append(f"int:11={q10(position.x / 10.24)}") - #bitstrm.append(f"int:11={q10(position.y / 10.24)}") - #bitstrm.append(f"int:10={q9(position.z / 5.12)}") + # posX = ctypes.c_int16( q10(position.x / 10.24) ).value + # posY = ctypes.c_int16( q10(position.y / 10.24) ).value + # posZ = ctypes.c_int16( q9(position.z / 5.12) ).value + # bitstrm.append(f"uintbe:8={ctypes.c_uint8(posX >> 3).value}") + # bitstrm.append(f"uintbe:8={ctypes.c_uint8(( (posX & MASK_3BIT) << 5 ) | (posY >> 6)).value}") + # bitstrm.append(f"uintbe:8={ctypes.c_uint8(( (posY & MASK_6BIT) << 2 ) | (posZ >> 8)).value}") + # bitstrm.append(f"uintbe:8={(posZ >> 2)}") + + bitstrm.append(f"int:11={q10(position.x / 10.24)}") + bitstrm.append(f"int:11={q10(position.y / 10.24)}") + bitstrm.append(f"int:10={q9(position.z / 5.12)}") def unpackOrientation(bitstrm: ConstBitStream, piSize: int) -> ORIENTATION: -- GitLab From 4c69474d9ecdfc222ad9f484f78d7481a15fe95d Mon Sep 17 00:00:00 2001 From: Erik Norvell Date: Wed, 19 Nov 2025 17:14:09 -0600 Subject: [PATCH 13/24] Update unpacking of unpackISMPositionCompact and unpackPositionCompact to support negative ints --- lib_util/ivas_rtp_pi_data.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/lib_util/ivas_rtp_pi_data.c b/lib_util/ivas_rtp_pi_data.c index 779e3fabb8..0c13eac82f 100644 --- a/lib_util/ivas_rtp_pi_data.c +++ b/lib_util/ivas_rtp_pi_data.c @@ -775,20 +775,14 @@ static ivas_error unpackPositionCompact( const uint8_t *buffer, uint32_t numData return IVAS_ERROR( IVAS_ERR_RTP_UNPACK_PI_DATA, "Incorrect size to unpack compact position PI data" ); } - int16_t value1 = -100; - int16_t value2 = 100; - uint16_t value1_uint16 = (uint16_t) value1; - uint16_t value2_uint16 = (uint16_t) value2; - - - - position->size = sizeof( IVAS_PIDATA_POSITION ); compactRead = ( (int32_t) buffer[0] << 24 ) | ( (int32_t) buffer[1] << 16 ) | ( (int32_t) buffer[2] << 8 ) | ( (int32_t) buffer[3] ); - position->position.x = FLOAT_FROM_Q10( (int16_t) ( compactRead >> 21 ) ) * MAX_PI_COMPACT_POSITION_XY_METERS; - position->position.y = FLOAT_FROM_Q10( ( (int16_t) ( compactRead >> 10 ) ) & MASK_11BIT ) * MAX_PI_COMPACT_POSITION_XY_METERS; - position->position.z = FLOAT_FROM_Q9( (int16_t) ( compactRead & MASK_10BIT ) ) * MAX_PI_COMPACT_POSITION_Z_METERS; + position->position.x = FLOAT_FROM_Q10( (int16_t) ( compactRead >> 21 ) ) * MAX_PI_COMPACT_POSITION_XY_METERS; /* Shift preserves sign bit */ + compactRead = compactRead << 11; /* Discard read bits */ + position->position.y = FLOAT_FROM_Q10( (int16_t) ( compactRead >> 21 ) ) * MAX_PI_COMPACT_POSITION_XY_METERS; /* Shift preserves sign bit */ + compactRead = compactRead << 11; /* Discard read bits */ + position->position.z = FLOAT_FROM_Q9( (int16_t) ( compactRead >> 22 ) ) * MAX_PI_COMPACT_POSITION_Z_METERS; /* Shift preserves sign bit */ return IVAS_ERR_OK; } @@ -915,9 +909,11 @@ static ivas_error unpackISMPositionCompact( const uint8_t *buffer, uint32_t numD for ( n = 0; n < ism_position->numObjects; n++ ) { compactRead = ( (int32_t) buffer[0] << 24 ) | ( (int32_t) buffer[1] << 16 ) | ( (int32_t) buffer[2] << 8 ) | ( (int32_t) buffer[3] ); - ism_position->position[n].x = FLOAT_FROM_Q10( (int16_t) ( compactRead >> 21 ) ) * MAX_PI_COMPACT_POSITION_XY_METERS; - ism_position->position[n].y = FLOAT_FROM_Q10( ( (int16_t) ( compactRead >> 10 ) ) & MASK_11BIT ) * MAX_PI_COMPACT_POSITION_XY_METERS; - ism_position->position[n].z = FLOAT_FROM_Q9( (int16_t) ( compactRead & MASK_10BIT ) ) * MAX_PI_COMPACT_POSITION_Z_METERS; + ism_position->position[n].x = FLOAT_FROM_Q10( (int16_t) ( compactRead >> 21 ) ) * MAX_PI_COMPACT_POSITION_XY_METERS; /* Shift preserves sign bit */ + compactRead = compactRead << 11; /* Discard read bits */ + ism_position->position[n].y = FLOAT_FROM_Q10( (int16_t) ( compactRead >> 21 ) ) * MAX_PI_COMPACT_POSITION_XY_METERS; /* Shift preserves sign bit */ + compactRead = compactRead << 11; /* Discard read bits */ + ism_position->position[n].z = FLOAT_FROM_Q9( (int16_t) ( compactRead >> 22 ) ) * MAX_PI_COMPACT_POSITION_Z_METERS; /* Shift preserves sign bit */ } return IVAS_ERR_OK; } -- GitLab From c41840bd9c563bbd6d221f313347cfba5be01066 Mon Sep 17 00:00:00 2001 From: Erik Norvell Date: Wed, 19 Nov 2025 17:26:42 -0600 Subject: [PATCH 14/24] Clang format --- lib_util/ivas_rtp_pi_data.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib_util/ivas_rtp_pi_data.c b/lib_util/ivas_rtp_pi_data.c index 0c13eac82f..2cf76b801c 100644 --- a/lib_util/ivas_rtp_pi_data.c +++ b/lib_util/ivas_rtp_pi_data.c @@ -779,10 +779,10 @@ static ivas_error unpackPositionCompact( const uint8_t *buffer, uint32_t numData compactRead = ( (int32_t) buffer[0] << 24 ) | ( (int32_t) buffer[1] << 16 ) | ( (int32_t) buffer[2] << 8 ) | ( (int32_t) buffer[3] ); position->position.x = FLOAT_FROM_Q10( (int16_t) ( compactRead >> 21 ) ) * MAX_PI_COMPACT_POSITION_XY_METERS; /* Shift preserves sign bit */ - compactRead = compactRead << 11; /* Discard read bits */ + compactRead = compactRead << 11; /* Discard read bits */ position->position.y = FLOAT_FROM_Q10( (int16_t) ( compactRead >> 21 ) ) * MAX_PI_COMPACT_POSITION_XY_METERS; /* Shift preserves sign bit */ - compactRead = compactRead << 11; /* Discard read bits */ - position->position.z = FLOAT_FROM_Q9( (int16_t) ( compactRead >> 22 ) ) * MAX_PI_COMPACT_POSITION_Z_METERS; /* Shift preserves sign bit */ + compactRead = compactRead << 11; /* Discard read bits */ + position->position.z = FLOAT_FROM_Q9( (int16_t) ( compactRead >> 22 ) ) * MAX_PI_COMPACT_POSITION_Z_METERS; /* Shift preserves sign bit */ return IVAS_ERR_OK; } @@ -910,10 +910,10 @@ static ivas_error unpackISMPositionCompact( const uint8_t *buffer, uint32_t numD { compactRead = ( (int32_t) buffer[0] << 24 ) | ( (int32_t) buffer[1] << 16 ) | ( (int32_t) buffer[2] << 8 ) | ( (int32_t) buffer[3] ); ism_position->position[n].x = FLOAT_FROM_Q10( (int16_t) ( compactRead >> 21 ) ) * MAX_PI_COMPACT_POSITION_XY_METERS; /* Shift preserves sign bit */ - compactRead = compactRead << 11; /* Discard read bits */ + compactRead = compactRead << 11; /* Discard read bits */ ism_position->position[n].y = FLOAT_FROM_Q10( (int16_t) ( compactRead >> 21 ) ) * MAX_PI_COMPACT_POSITION_XY_METERS; /* Shift preserves sign bit */ - compactRead = compactRead << 11; /* Discard read bits */ - ism_position->position[n].z = FLOAT_FROM_Q9( (int16_t) ( compactRead >> 22 ) ) * MAX_PI_COMPACT_POSITION_Z_METERS; /* Shift preserves sign bit */ + compactRead = compactRead << 11; /* Discard read bits */ + ism_position->position[n].z = FLOAT_FROM_Q9( (int16_t) ( compactRead >> 22 ) ) * MAX_PI_COMPACT_POSITION_Z_METERS; /* Shift preserves sign bit */ } return IVAS_ERR_OK; } -- GitLab From 29be5676cb34b52d14922cf04d5386b365c8654a Mon Sep 17 00:00:00 2001 From: Lauros Pajunen Date: Wed, 19 Nov 2025 17:34:33 -0600 Subject: [PATCH 15/24] Enable all rtpdump tests --- tests/rtp/test_rtp.py | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/tests/rtp/test_rtp.py b/tests/rtp/test_rtp.py index 8eea91c8ee..b385ab80f2 100644 --- a/tests/rtp/test_rtp.py +++ b/tests/rtp/test_rtp.py @@ -193,15 +193,10 @@ def generatePiData(startTs: int, endTs: int) -> dict: y=random.randint(-32788, 32767) / 100.0, z=random.randint(-32788, 32767) / 100.0, ) - #somePositionCompact = lambda: POSITION( - # x=random.randint(-1024, 1023) / 100.0, - # y=random.randint(-1024, 1023) / 100.0, - # z=random.randint(-512, 511) / 100.0, - #) somePositionCompact = lambda: POSITION( - x=1.0, - y=1.0, - z=-1.0, + x=random.randint(-1024, 1023) / 100.0, + y=random.randint(-1024, 1023) / 100.0, + z=random.randint(-512, 511) / 100.0, ) someDesc = lambda: AUDIO_DESCRIPTION( isSpeech=bool(random.getrandbits(1)), @@ -295,11 +290,6 @@ def generatePiData(startTs: int, endTs: int) -> dict: for ts in range(startTs, endTs, 320): pidata = dict() - - pidata["ISM_NUM"] = someNumISM() - pidata["ISM_POSITION_COMPACT"] = someISMPositionsCompact(pidata["ISM_NUM"].num) - #pidata["R_ISM_POSITION_COMPACT"] = somePositionCompact() - ''' pidata["SCENE_ORIENTATION"] = someOrientation() pidata["DEVICE_ORIENTATION_COMPENSATED"] = someOrientation() pidata["DEVICE_ORIENTATION_UNCOMPENSATED"] = someOrientation() @@ -327,7 +317,6 @@ def generatePiData(startTs: int, endTs: int) -> dict: pidata["R_ISM_POSITION"] = somePosition() pidata["R_ISM_POSITION_COMPACT"] = somePositionCompact() pidata["R_ISM_DIRECTION"] = someReverseISMDirection() - ''' data[str(ts)] = pidata return data -- GitLab From a626cd33b3b1d0321a077fe1984e6e524c5a1a48 Mon Sep 17 00:00:00 2001 From: Lauros Pajunen Date: Wed, 19 Nov 2025 17:58:18 -0600 Subject: [PATCH 16/24] Increment buffer after each ISM read --- lib_util/ivas_rtp_pi_data.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_util/ivas_rtp_pi_data.c b/lib_util/ivas_rtp_pi_data.c index 2cf76b801c..e02ee12c22 100644 --- a/lib_util/ivas_rtp_pi_data.c +++ b/lib_util/ivas_rtp_pi_data.c @@ -908,7 +908,7 @@ static ivas_error unpackISMPositionCompact( const uint8_t *buffer, uint32_t numD for ( n = 0; n < ism_position->numObjects; n++ ) { - compactRead = ( (int32_t) buffer[0] << 24 ) | ( (int32_t) buffer[1] << 16 ) | ( (int32_t) buffer[2] << 8 ) | ( (int32_t) buffer[3] ); + compactRead = ( (int32_t) buffer[n*4] << 24 ) | ( (int32_t) buffer[n*4 + 1] << 16 ) | ( (int32_t) buffer[n*4 + 2] << 8 ) | ( (int32_t) buffer[n*4 + 3] ); ism_position->position[n].x = FLOAT_FROM_Q10( (int16_t) ( compactRead >> 21 ) ) * MAX_PI_COMPACT_POSITION_XY_METERS; /* Shift preserves sign bit */ compactRead = compactRead << 11; /* Discard read bits */ ism_position->position[n].y = FLOAT_FROM_Q10( (int16_t) ( compactRead >> 21 ) ) * MAX_PI_COMPACT_POSITION_XY_METERS; /* Shift preserves sign bit */ -- GitLab From e93e1dd50cbd90aed60e54a3b0538b518bc69b73 Mon Sep 17 00:00:00 2001 From: Lauros Pajunen Date: Wed, 19 Nov 2025 18:01:01 -0600 Subject: [PATCH 17/24] Clang --- lib_util/ivas_rtp_pi_data.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_util/ivas_rtp_pi_data.c b/lib_util/ivas_rtp_pi_data.c index e02ee12c22..af1143990f 100644 --- a/lib_util/ivas_rtp_pi_data.c +++ b/lib_util/ivas_rtp_pi_data.c @@ -908,7 +908,7 @@ static ivas_error unpackISMPositionCompact( const uint8_t *buffer, uint32_t numD for ( n = 0; n < ism_position->numObjects; n++ ) { - compactRead = ( (int32_t) buffer[n*4] << 24 ) | ( (int32_t) buffer[n*4 + 1] << 16 ) | ( (int32_t) buffer[n*4 + 2] << 8 ) | ( (int32_t) buffer[n*4 + 3] ); + compactRead = ( (int32_t) buffer[n * 4] << 24 ) | ( (int32_t) buffer[n * 4 + 1] << 16 ) | ( (int32_t) buffer[n * 4 + 2] << 8 ) | ( (int32_t) buffer[n * 4 + 3] ); ism_position->position[n].x = FLOAT_FROM_Q10( (int16_t) ( compactRead >> 21 ) ) * MAX_PI_COMPACT_POSITION_XY_METERS; /* Shift preserves sign bit */ compactRead = compactRead << 11; /* Discard read bits */ ism_position->position[n].y = FLOAT_FROM_Q10( (int16_t) ( compactRead >> 21 ) ) * MAX_PI_COMPACT_POSITION_XY_METERS; /* Shift preserves sign bit */ -- GitLab From 17ea1e5e371a18e63670eb56c7b6b8bcd1b51c1b Mon Sep 17 00:00:00 2001 From: Erik Norvell Date: Wed, 19 Nov 2025 20:00:06 -0600 Subject: [PATCH 18/24] Remove include of tools.c and write max abs search with loop --- lib_util/ivas_rtp_pi_data.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/lib_util/ivas_rtp_pi_data.c b/lib_util/ivas_rtp_pi_data.c index dd00716f6c..31ebe1c21c 100644 --- a/lib_util/ivas_rtp_pi_data.c +++ b/lib_util/ivas_rtp_pi_data.c @@ -37,9 +37,6 @@ #endif #ifdef ISM_PI_DATA #include -#ifdef COMPACT_ORIENTATION_PI_DATA -#include "tools.c" -#endif #ifndef min #define min( x, y ) ( ( x ) < ( y ) ? ( x ) : ( y ) ) @@ -122,7 +119,17 @@ static uint32_t packQuaternion( IVAS_QUATERNION orientation, uint8_t *buffer ) q[2] = orientation.y; q[3] = orientation.z; - max_q_idx = maximumAbs( q, 4, &q_max ); + max_q_idx = 0; + q_max = (float) fabs( q[0] ); + for ( n = 1; n < 4; n++ ) + { + if ( (float) fabs( q[n] ) > q_max ) + { + q_max = (float) fabs( q[n] ); + max_q_idx = n; + } + } + if ( q[max_q_idx] < 0 ) { for ( n = 0; n < 4; n++ ) -- GitLab From bd58ce5e38060824f5d3695e7cb4ded130ae72f7 Mon Sep 17 00:00:00 2001 From: Erik Norvell Date: Wed, 19 Nov 2025 20:12:42 -0600 Subject: [PATCH 19/24] Use unsigned int for compactRead variable for bit-wise operations --- lib_util/ivas_rtp_pi_data.c | 8 ++++---- tests/rtp/ivasrtp.py | 10 ---------- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/lib_util/ivas_rtp_pi_data.c b/lib_util/ivas_rtp_pi_data.c index af1143990f..cd721ca2c8 100644 --- a/lib_util/ivas_rtp_pi_data.c +++ b/lib_util/ivas_rtp_pi_data.c @@ -767,7 +767,7 @@ static ivas_error packPositionCompact( const IVAS_PIDATA_GENERIC *piData, uint8_ static ivas_error unpackPositionCompact( const uint8_t *buffer, uint32_t numDataBytes, IVAS_PIDATA_GENERIC *piData ) { IVAS_PIDATA_POSITION *position = (IVAS_PIDATA_POSITION *) piData; - int32_t compactRead = 0; + uint32_t compactRead = 0; /* Compact position data is 4 bytes */ if ( numDataBytes != 4 ) @@ -777,7 +777,7 @@ static ivas_error unpackPositionCompact( const uint8_t *buffer, uint32_t numData position->size = sizeof( IVAS_PIDATA_POSITION ); - compactRead = ( (int32_t) buffer[0] << 24 ) | ( (int32_t) buffer[1] << 16 ) | ( (int32_t) buffer[2] << 8 ) | ( (int32_t) buffer[3] ); + compactRead = ( (uint32_t) buffer[0] << 24 ) | ( (uint32_t) buffer[1] << 16 ) | ( (uint32_t) buffer[2] << 8 ) | ( (uint32_t) buffer[3] ); position->position.x = FLOAT_FROM_Q10( (int16_t) ( compactRead >> 21 ) ) * MAX_PI_COMPACT_POSITION_XY_METERS; /* Shift preserves sign bit */ compactRead = compactRead << 11; /* Discard read bits */ position->position.y = FLOAT_FROM_Q10( (int16_t) ( compactRead >> 21 ) ) * MAX_PI_COMPACT_POSITION_XY_METERS; /* Shift preserves sign bit */ @@ -893,7 +893,7 @@ static ivas_error packISMPositionCompact( const IVAS_PIDATA_GENERIC *piData, uin static ivas_error unpackISMPositionCompact( const uint8_t *buffer, uint32_t numDataBytes, IVAS_PIDATA_GENERIC *piData ) { uint16_t n; - int32_t compactRead = 0; + uint32_t compactRead = 0; IVAS_PIDATA_ISM_POSITION *ism_position = (IVAS_PIDATA_ISM_POSITION *) piData; /* Compact position data is 4 bytes */ @@ -908,7 +908,7 @@ static ivas_error unpackISMPositionCompact( const uint8_t *buffer, uint32_t numD for ( n = 0; n < ism_position->numObjects; n++ ) { - compactRead = ( (int32_t) buffer[n * 4] << 24 ) | ( (int32_t) buffer[n * 4 + 1] << 16 ) | ( (int32_t) buffer[n * 4 + 2] << 8 ) | ( (int32_t) buffer[n * 4 + 3] ); + compactRead = ( (uint32_t) buffer[n * 4] << 24 ) | ( (uint32_t) buffer[n * 4 + 1] << 16 ) | ( (uint32_t) buffer[n * 4 + 2] << 8 ) | ( (uint32_t) buffer[n * 4 + 3] ); ism_position->position[n].x = FLOAT_FROM_Q10( (int16_t) ( compactRead >> 21 ) ) * MAX_PI_COMPACT_POSITION_XY_METERS; /* Shift preserves sign bit */ compactRead = compactRead << 11; /* Discard read bits */ ism_position->position[n].y = FLOAT_FROM_Q10( (int16_t) ( compactRead >> 21 ) ) * MAX_PI_COMPACT_POSITION_XY_METERS; /* Shift preserves sign bit */ diff --git a/tests/rtp/ivasrtp.py b/tests/rtp/ivasrtp.py index aec9d4cbe3..c1ecf77bb0 100644 --- a/tests/rtp/ivasrtp.py +++ b/tests/rtp/ivasrtp.py @@ -826,16 +826,6 @@ def packPositionsCompact(bitstrm: BitStream, data: any): assert ( type(position) == POSITION ), "Compact position PI Data expects a data of type list[POSITIONS]" - #posX = np.uint16(q10(position.x / 10.24)) - #posY = np.uint16(q10(position.y / 10.24)) - #posZ = np.uint16(q9(position.z / 5.12)) - # posX = ctypes.c_int16( q10(position.x / 10.24) ).value - # posY = ctypes.c_int16( q10(position.y / 10.24) ).value - # posZ = ctypes.c_int16( q9(position.z / 5.12) ).value - # bitstrm.append(f"uintbe:8={ctypes.c_uint8(posX >> 3).value}") - # bitstrm.append(f"uintbe:8={ctypes.c_uint8(( (posX & MASK_3BIT) << 5 ) | (posY >> 6)).value}") - # bitstrm.append(f"uintbe:8={ctypes.c_uint8(( (posY & MASK_6BIT) << 2 ) | (posZ >> 8)).value}") - # bitstrm.append(f"uintbe:8={(posZ >> 2)}") bitstrm.append(f"int:11={q10(position.x / 10.24)}") bitstrm.append(f"int:11={q10(position.y / 10.24)}") -- GitLab From e7a10462d7f155c5f93fc4c40c60a5cb35b79961 Mon Sep 17 00:00:00 2001 From: Erik Norvell Date: Wed, 19 Nov 2025 20:39:20 -0600 Subject: [PATCH 20/24] Revert fix on unsigned buffer --- lib_util/ivas_rtp_pi_data.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib_util/ivas_rtp_pi_data.c b/lib_util/ivas_rtp_pi_data.c index 0b9804eddf..31ebe1c21c 100644 --- a/lib_util/ivas_rtp_pi_data.c +++ b/lib_util/ivas_rtp_pi_data.c @@ -873,7 +873,7 @@ static ivas_error packPositionCompact( const IVAS_PIDATA_GENERIC *piData, uint8_ static ivas_error unpackPositionCompact( const uint8_t *buffer, uint32_t numDataBytes, IVAS_PIDATA_GENERIC *piData ) { IVAS_PIDATA_POSITION *position = (IVAS_PIDATA_POSITION *) piData; - uint32_t compactRead = 0; + int32_t compactRead = 0; /* Compact position data is 4 bytes */ if ( numDataBytes != 4 ) @@ -883,7 +883,7 @@ static ivas_error unpackPositionCompact( const uint8_t *buffer, uint32_t numData position->size = sizeof( IVAS_PIDATA_POSITION ); - compactRead = ( (uint32_t) buffer[0] << 24 ) | ( (uint32_t) buffer[1] << 16 ) | ( (uint32_t) buffer[2] << 8 ) | ( (uint32_t) buffer[3] ); + compactRead = ( (int32_t) buffer[0] << 24 ) | ( (int32_t) buffer[1] << 16 ) | ( (int32_t) buffer[2] << 8 ) | ( (int32_t) buffer[3] ); position->position.x = FLOAT_FROM_Q10( (int16_t) ( compactRead >> 21 ) ) * MAX_PI_COMPACT_POSITION_XY_METERS; /* Shift preserves sign bit */ compactRead = compactRead << 11; /* Discard read bits */ position->position.y = FLOAT_FROM_Q10( (int16_t) ( compactRead >> 21 ) ) * MAX_PI_COMPACT_POSITION_XY_METERS; /* Shift preserves sign bit */ @@ -999,7 +999,7 @@ static ivas_error packISMPositionCompact( const IVAS_PIDATA_GENERIC *piData, uin static ivas_error unpackISMPositionCompact( const uint8_t *buffer, uint32_t numDataBytes, IVAS_PIDATA_GENERIC *piData ) { uint16_t n; - uint32_t compactRead = 0; + int32_t compactRead = 0; IVAS_PIDATA_ISM_POSITION *ism_position = (IVAS_PIDATA_ISM_POSITION *) piData; /* Compact position data is 4 bytes */ @@ -1014,7 +1014,7 @@ static ivas_error unpackISMPositionCompact( const uint8_t *buffer, uint32_t numD for ( n = 0; n < ism_position->numObjects; n++ ) { - compactRead = ( (uint32_t) buffer[n * 4] << 24 ) | ( (uint32_t) buffer[n * 4 + 1] << 16 ) | ( (uint32_t) buffer[n * 4 + 2] << 8 ) | ( (uint32_t) buffer[n * 4 + 3] ); + compactRead = ( (int32_t) buffer[n * 4] << 24 ) | ( (int32_t) buffer[n * 4 + 1] << 16 ) | ( (int32_t) buffer[n * 4 + 2] << 8 ) | ( (int32_t) buffer[n * 4 + 3] ); ism_position->position[n].x = FLOAT_FROM_Q10( (int16_t) ( compactRead >> 21 ) ) * MAX_PI_COMPACT_POSITION_XY_METERS; /* Shift preserves sign bit */ compactRead = compactRead << 11; /* Discard read bits */ ism_position->position[n].y = FLOAT_FROM_Q10( (int16_t) ( compactRead >> 21 ) ) * MAX_PI_COMPACT_POSITION_XY_METERS; /* Shift preserves sign bit */ -- GitLab From a524291b074814967a2d3c4b38aba4505cfe6383 Mon Sep 17 00:00:00 2001 From: Erik Norvell Date: Wed, 19 Nov 2025 21:00:29 -0600 Subject: [PATCH 21/24] Fix for usan error --- lib_util/ivas_rtp_pi_data.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib_util/ivas_rtp_pi_data.c b/lib_util/ivas_rtp_pi_data.c index 31ebe1c21c..f9999ac89c 100644 --- a/lib_util/ivas_rtp_pi_data.c +++ b/lib_util/ivas_rtp_pi_data.c @@ -165,10 +165,10 @@ static ivas_error unpackQuaternion( const uint8_t *buffer, IVAS_QUATERNION *orie uint16_t max_q_idx, tmp; float q[4], qs; - lWord = ( buffer[0] ) << 24; - lWord |= ( buffer[1] ) << 16; - lWord |= ( buffer[2] ) << 8; - lWord |= buffer[3]; + lWord = ( (uint32_t) buffer[0] ) << 24; + lWord |= ( (uint32_t) buffer[1] ) << 16; + lWord |= ( (uint32_t) buffer[2] ) << 8; + lWord |= (uint32_t) buffer[3]; max_q_idx = ( lWord >> 30 ) & MASK_2BIT; k = 1; -- GitLab From 472474a9e2d20b2736101aa87f043248a296450d Mon Sep 17 00:00:00 2001 From: Erik Norvell Date: Wed, 19 Nov 2025 21:34:43 -0600 Subject: [PATCH 22/24] Another usan fix --- lib_util/ivas_rtp_pi_data.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_util/ivas_rtp_pi_data.c b/lib_util/ivas_rtp_pi_data.c index f9999ac89c..b7ca5a91a4 100644 --- a/lib_util/ivas_rtp_pi_data.c +++ b/lib_util/ivas_rtp_pi_data.c @@ -137,7 +137,7 @@ static uint32_t packQuaternion( IVAS_QUATERNION orientation, uint8_t *buffer ) q[n] = -q[n]; } } - lWord = max_q_idx << 30; + lWord = ( (uint32_t) max_q_idx ) << 30; k = 1; for ( n = 0; n < 4; n++ ) -- GitLab From 38cd955b11d9c809673699e845ddbbfa2c1c1e8c Mon Sep 17 00:00:00 2001 From: Erik Norvell Date: Wed, 19 Nov 2025 22:33:18 -0600 Subject: [PATCH 23/24] Test efficient scaling of Quaternions --- lib_util/ivas_rtp_pi_data.c | 4 ++-- tests/rtp/ivasrtp.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib_util/ivas_rtp_pi_data.c b/lib_util/ivas_rtp_pi_data.c index b7ca5a91a4..425484f47b 100644 --- a/lib_util/ivas_rtp_pi_data.c +++ b/lib_util/ivas_rtp_pi_data.c @@ -146,7 +146,7 @@ static uint32_t packQuaternion( IVAS_QUATERNION orientation, uint8_t *buffer ) { continue; } - lWord |= ( ( (int16_t) ( ( q[n] + 1 ) * 1023 * 0.5f ) & MASK_10BIT ) << ( 30 - k * 10 ) ); + lWord |= ( ( (int16_t) ( ( q[n] + 1 / sqrt( 2.0f ) ) * 1023 * sqrt( 2.0f ) ) & MASK_10BIT ) << ( 30 - k * 10 ) ); k++; } @@ -180,7 +180,7 @@ static ivas_error unpackQuaternion( const uint8_t *buffer, IVAS_QUATERNION *orie continue; } tmp = ( lWord >> ( 30 - k * 10 ) ) & MASK_10BIT; - q[i] = tmp / 1023.0f * 2.0f - 1; + q[i] = tmp / 1023.0f * sqrtf( 2.0f ) - 1 / sqrtf( 2.0f ); qs += q[i] * q[i]; k++; } diff --git a/tests/rtp/ivasrtp.py b/tests/rtp/ivasrtp.py index c66bb497fb..9da75180e9 100644 --- a/tests/rtp/ivasrtp.py +++ b/tests/rtp/ivasrtp.py @@ -769,7 +769,7 @@ def unpackOrientations(bitstrm: ConstBitStream, piSize: int) -> list[ORIENTATION if i == max_q_idx: continue tmp = bitstrm.read(10).uint - q[i] = (tmp / 1023.0) * 2.0 - 1.0 + q[i] = (tmp / 1023.0) * 2.0**0.5 - 1.0 / (2.0**0.5) qs = qs + q[i]**2 q[max_q_idx] = (1 - qs)**0.5 @@ -798,7 +798,7 @@ def packOrientations(bitstrm: BitStream, data: any): for i in range(0,4): if i == max_q_idx: continue - bitstrm.append(f"uint:10={(int)((q[i]+1)*1023*1/2)}") + bitstrm.append(f"uint:10={(int)((q[i]+1/(2**0.5))*1023*(2**0.5))}") def unpackPositions(bitstrm: ConstBitStream, piSize: int) -> list[POSITION]: -- GitLab From 3416bd7f58cee25c59cc73328a0b777a3fe54c4a Mon Sep 17 00:00:00 2001 From: Erik Norvell Date: Wed, 19 Nov 2025 22:41:16 -0600 Subject: [PATCH 24/24] Fix --- lib_util/ivas_rtp_pi_data.c | 2 +- tests/rtp/ivasrtp.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib_util/ivas_rtp_pi_data.c b/lib_util/ivas_rtp_pi_data.c index 425484f47b..10adfc7ba6 100644 --- a/lib_util/ivas_rtp_pi_data.c +++ b/lib_util/ivas_rtp_pi_data.c @@ -146,7 +146,7 @@ static uint32_t packQuaternion( IVAS_QUATERNION orientation, uint8_t *buffer ) { continue; } - lWord |= ( ( (int16_t) ( ( q[n] + 1 / sqrt( 2.0f ) ) * 1023 * sqrt( 2.0f ) ) & MASK_10BIT ) << ( 30 - k * 10 ) ); + lWord |= ( ( (int16_t) ( ( q[n] + 1 / sqrt( 2.0f ) ) * 1023 / sqrt( 2.0f ) ) & MASK_10BIT ) << ( 30 - k * 10 ) ); k++; } diff --git a/tests/rtp/ivasrtp.py b/tests/rtp/ivasrtp.py index 9da75180e9..ad54db8d35 100644 --- a/tests/rtp/ivasrtp.py +++ b/tests/rtp/ivasrtp.py @@ -798,7 +798,7 @@ def packOrientations(bitstrm: BitStream, data: any): for i in range(0,4): if i == max_q_idx: continue - bitstrm.append(f"uint:10={(int)((q[i]+1/(2**0.5))*1023*(2**0.5))}") + bitstrm.append(f"uint:10={(int)((q[i]+1/(2**0.5))*1023/(2**0.5))}") def unpackPositions(bitstrm: ConstBitStream, piSize: int) -> list[POSITION]: -- GitLab