diff --git a/lib_com/options.h b/lib_com/options.h index 7aa9f1c91547b45b18620de0c0715d221efc4f31..9e2052b43b8b3a7b1414469911054d74ff74e0d6 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -169,6 +169,8 @@ #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 */ +#define COMPACT_ORIENTATION_PI_DATA /* ################### Start BE switches ################################# */ /* only BE switches wrt selection floating point code */ diff --git a/lib_util/ivas_rtp_file.c b/lib_util/ivas_rtp_file.c index b8e79fad53158de060083438cabeaac72fe0d7cb..009a158c49ee22d121f172195332d64975bc1439 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 a550892548f3b0d82815ca935562b13c8a23d306..2ab816fab730714db8e3a0469ef5fddd74765b8f 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 = 0x3FF, + MASK_11BIT = 0x7FF, +#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_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 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 0398d9ce401ff633a1b52d48b5533e0daeb193eb..6a816f36de3bb5ae000ef745aa73a00b90661477 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 ) { @@ -1585,6 +1586,18 @@ 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 += isFirstPiSize ? ( byte & MASK_5BIT ) : byte; + if ( nBytes >= payload->length ) + { + return IVAS_ERROR( IVAS_ERR_RTP_UNDERFLOW, "Underflow during reading piSize" ); + } + isFirstPiSize = false; + } while ( byte == 255 || piSize == 32 ); +#else do { byte = payload->buffer[nBytes++]; @@ -1594,6 +1607,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 b9b7bcc7e44fbd19ca75570c793acd9e697bc588..10adfc7ba699275bf5892d386be4b309ed62c2f8 100644 --- a/lib_util/ivas_rtp_pi_data.c +++ b/lib_util/ivas_rtp_pi_data.c @@ -79,6 +79,137 @@ static int16_t ivasPayload_convertToQ15( float value ) return (int16_t) ( value ); } +#ifdef RTP_UPDATES_SA4_134 +/*-----------------------------------------------------------------------* + * 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_convertToQ9() + * + * Convert a float value into a Q9 encoded value. + *-----------------------------------------------------------------------*/ +static int16_t ivasPayload_convertToQ9( float value ) +{ + value = ( value * 512.0f ); + value = value > +512.0f ? +512.0f : value; + value = value < -512.0f ? -512.0f : 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 = 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++ ) + { + q[n] = -q[n]; + } + } + lWord = ( (uint32_t) max_q_idx ) << 30; + + k = 1; + for ( n = 0; n < 4; n++ ) + { + if ( n == max_q_idx ) + { + continue; + } + lWord |= ( ( (int16_t) ( ( q[n] + 1 / sqrt( 2.0f ) ) * 1023 / sqrt( 2.0f ) ) & 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 = ( (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; + 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 * sqrtf( 2.0f ) - 1 / sqrtf( 2.0f ); + 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; +} + +#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 ) { (void) piData; @@ -152,18 +283,38 @@ 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; +#ifdef COMPACT_ORIENTATION_PI_DATA + nBytes += packQuaternion( orientation->orientation, &buffer[nBytes] ); +#else + 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 ); +#endif +#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 +337,35 @@ 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++ ) + { +#ifdef COMPACT_ORIENTATION_PI_DATA + nBytes += packQuaternion( orientation->orientation[n], &buffer[nBytes] ); +#else + 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 ); +#endif + } +#else buffer[nBytes++] = (uint8_t) orientation->numObjects * 8; for ( n = 0; n < orientation->numObjects; n++ ) { @@ -201,6 +374,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 +384,23 @@ 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 ); +#ifdef COMPACT_ORIENTATION_PI_DATA + unpackQuaternion( buffer, &( orientation->orientation ) ); +#else + 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] ); +#endif +#else /* Orientation data is 8 bytes */ if ( numDataBytes != 8 ) { @@ -217,11 +408,12 @@ static ivas_error unpackOrientation( const uint8_t *buffer, uint32_t numDataByte } piData->size = sizeof( IVAS_PIDATA_ORIENTATION ); + 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,6 +422,29 @@ 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++ ) + { +#ifdef COMPACT_ORIENTATION_PI_DATA + unpackQuaternion( &buffer[4 * n], &( ism_orientation->orientation[n] ) ); +#else + 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] ); +#endif + } +#else /* Orientation data is 8 bytes */ uint16_t n; if ( numDataBytes % 8 != 0 ) @@ -247,6 +462,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 +830,70 @@ 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_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 ); + 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; + int32_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 = ( (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 */ + 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; +} +#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 +955,76 @@ 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_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 ); + 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; + int32_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_COMPACT; + ism_position->numObjects = (uint16_t) numDataBytes / 4; + + 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] ); + 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; +} +#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 +1102,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 +1120,7 @@ static ivas_error packAudioFocusCommon( const IVAS_PIDATA_GENERIC *piData, uint8 { packedSize = 8; } +#endif else if ( audioFocus->availLevel ) { packedSize = 1; @@ -778,6 +1139,23 @@ 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 ) + { +#ifdef COMPACT_ORIENTATION_PI_DATA + nBytes += packQuaternion( audioFocus->direction, &buffer[nBytes] ); +#else + 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 ); +#endif + } + 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 +1167,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 +1177,38 @@ 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 + { +#ifdef COMPACT_ORIENTATION_PI_DATA + unpackQuaternion( buffer, &( audioFocus->direction ) ); +#else + 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] ); +#endif + + 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 +1235,7 @@ static ivas_error unpackAudioFocusCommon( const uint8_t *buffer, uint32_t numDat audioFocus->flvl = ( buffer[8] >> 4 ); } } +#endif return IVAS_ERR_OK; } @@ -1462,11 +1874,14 @@ 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 */ +#endif packISMDistanceAttenuation, /* ISM_DISTANCE_ATTENUATION */ packISMDirectivity, /* ISM_DIRECTIVITY */ #else @@ -1483,27 +1898,37 @@ static const PACK_PI_FN packPiDataFuntions[IVAS_PI_MAX_ID] = { #else packUnsupportedData, /* DIEGETIC_TYPE */ #endif - packUnsupportedData, /* RESERVED13 */ +#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 */ #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 */ #endif - packDynamicSuppression, /* DYNAMIC_AUDIO_SUPPRESSION */ - 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 */ @@ -1526,7 +1951,10 @@ 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 */ +#endif packReverseISMDirection, /* R_ISM_DIRECTION */ #else packUnsupportedData, /* R_ISM_POSITION */ @@ -1535,8 +1963,10 @@ static const PACK_PI_FN packPiDataFuntions[IVAS_PI_MAX_ID] = { packUnsupportedData, /* RESERVED27 */ packUnsupportedData, /* RESERVED28 */ packUnsupportedData, /* RESERVED29 */ +#ifndef RTP_UPDATES_SA4_134 packUnsupportedData, /* RESERVED30 */ - packNoPiData /* NO_DATA */ +#endif + packNoPiData /* NO_DATA */ }; static const UNPACK_PI_FN unpackPiDataFuntions[IVAS_PI_MAX_ID] = { @@ -1550,11 +1980,14 @@ 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 */ +#endif unpackISMDistanceAttenuation, /* ISM_DISTANCE_ATTENUATION */ unpackISMDirectivity, /* ISM_DIRECTIVITY */ #else @@ -1571,27 +2004,37 @@ 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 */ #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 */ - unpackAudioFocusCommon, /* AUDIO_FOCUS_REQUEST */ +#endif + unpackAudioFocusCommon, /* AUDIO_FOCUS_REQUEST */ #ifdef PI_LATENCY unpackPiLatency, /* PI_LATENCY */ #else - unpackUnsupportedData, /* PI_LATENCY */ + unpackUnsupportedData, /* PI_LATENCY */ #endif #else unpackUnsupportedData, /* PLAYBACK_DEVICE_ORIENTATION */ @@ -1614,7 +2057,10 @@ 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 */ +#endif unpackReverseISMDirection, /* R_ISM_DIRECTION */ #else unpackUnsupportedData, /* R_ISM_POSITION */ @@ -1623,10 +2069,48 @@ static const UNPACK_PI_FN unpackPiDataFuntions[IVAS_PI_MAX_ID] = { unpackUnsupportedData, /* RESERVED27 */ unpackUnsupportedData, /* RESERVED28 */ unpackUnsupportedData, /* RESERVED29 */ +#ifndef RTP_UPDATES_SA4_134 unpackUnsupportedData, /* RESERVED30 */ - unpackNoPiData /* NO_DATA */ +#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 +2145,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 95a2ac99429f7ba825e594eee4bf56d1dfdb1309..fa319c6b2ed7fb27d9a19fd4cfc016775f5532f3 100644 --- a/lib_util/ivas_rtp_pi_data.h +++ b/lib_util/ivas_rtp_pi_data.h @@ -55,18 +55,23 @@ 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 */ +#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) */ - IVAS_PI_RESERVED15, /* reserved */ +#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,14 +84,19 @@ 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 */ - 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_RESERVED30, /* reserved */ -#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 */ +#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 */ } IVAS_PI_TYPE; /* cartesian coordinates (X,Y,Z) in 3D space */ @@ -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 5b1bb2be7948643fbe9b8c01768e4b3193a64564..ad54db8d35d6a14150de0f7213c82fe1ceef9a08 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" @@ -174,12 +176,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 +192,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 +411,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 @@ -654,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): @@ -727,6 +734,9 @@ cmrLookup = [ ] q15 = lambda x: int(min(32767.0, max(-32768.0, x * 32768.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))) def unpackUnsupported(bitstrm: ConstBitStream, piSize: int) -> any: @@ -748,16 +758,28 @@ 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() + 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**0.5 - 1.0 / (2.0**0.5) + 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 +789,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/(2**0.5))*1023/(2**0.5))}") def unpackPositions(bitstrm: ConstBitStream, piSize: int) -> list[POSITION]: @@ -797,9 +825,33 @@ 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"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: - 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 +877,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 +1037,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 +1045,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 +1228,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 +1244,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 +1263,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 +1279,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 ] diff --git a/tests/rtp/test_rtp.py b/tests/rtp/test_rtp.py index 53cb6488c5768ab3266bcaf3fe3a763592e126db..8ef0f57c701e19235cf996d7e0a60e8b3b470619 100644 --- a/tests/rtp/test_rtp.py +++ b/tests/rtp/test_rtp.py @@ -182,17 +182,27 @@ 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, 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)), @@ -209,23 +219,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,8 +268,9 @@ 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)] + 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 +297,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 +305,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 @@ -322,10 +320,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 +390,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" @@ -750,7 +748,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":