diff --git a/lib_com/options.h b/lib_com/options.h old mode 100755 new mode 100644 index cfdbd147006279ba5cf9bd18c667e0be097812cb..cb8899ca7805886499860f44fb6df84c7bd791bf --- a/lib_com/options.h +++ b/lib_com/options.h @@ -163,6 +163,7 @@ #define IVAS_RTPDUMP /* RTPDUMP writing and reading for IVAS payloads */ #define IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT /* RTPDUMP acoustic environment */ #define FIXED_RTP_SEQUENCE_NUM /* Remove random sequence number initialization */ +#define ISM_PI_DATA /* Add reading and packing/unpacking of ISM PI data */ /* ################### Start BE switches ################################# */ /* only BE switches wrt selection floating point code */ diff --git a/lib_util/ivas_rtp_file.c b/lib_util/ivas_rtp_file.c index 2838cd641a42321fbe31dafad427dd998a24e694..4ace9efd9045de695bef153028b7137d671dcea0 100644 --- a/lib_util/ivas_rtp_file.c +++ b/lib_util/ivas_rtp_file.c @@ -152,13 +152,16 @@ void IVAS_RTP_LogPiData( uint32_t nPiDataPresent /* i : Number of valid elements in the piData array */ ) { +#ifdef ISM_PI_DATA + uint16_t n; +#endif uint32_t timestamp = ~0u; if ( f_piDataOut == NULL || piData == NULL || nPiDataPresent == 0 ) { return; } -#ifdef IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT +#if defined IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT || defined ISM_PI_DATA #ifdef _WIN32 if ( ftell( f_piDataOut ) > 3 ) #else @@ -332,6 +335,104 @@ void IVAS_RTP_LogPiData( fprintf( f_piDataOut, "{}" ); } break; +#ifdef ISM_PI_DATA + case IVAS_PI_ISM_ORIENTATION: + { + fprintf( f_piDataOut, "[\n" ); + for ( n = 0; n < cur->data.ismOrientation.numObjects; n++ ) + { + if ( n != 0 ) + { + fprintf( f_piDataOut, ",\n" ); + } + fprintf( f_piDataOut, "\t\t\t{\n\t\t\t\t\"w\": %f,\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.ismOrientation.orientation[n].w, cur->data.ismOrientation.orientation[n].x, cur->data.ismOrientation.orientation[n].y, cur->data.ismOrientation.orientation[n].z ); + } + fprintf( f_piDataOut, "\n\t\t]" ); + } + break; + case IVAS_PI_ISM_NUM: + { + fprintf( f_piDataOut, "{\n" ); + fprintf( f_piDataOut, "\t\t\t\"num\": %d", cur->data.ismNum.numObjects ); + fprintf( f_piDataOut, "\n\t\t}" ); + } + break; + case IVAS_PI_ISM_ID: + { + fprintf( f_piDataOut, "{\n" ); + fprintf( f_piDataOut, "\t\t\t\"ids\": [\n" ); + for ( n = 0; n < cur->data.ismId.numObjects; n++ ) + { + if ( n != 0 ) + { + fprintf( f_piDataOut, ",\n" ); + } + fprintf( f_piDataOut, "\t\t\t\t%d", cur->data.ismId.id[n] ); + } + fprintf( f_piDataOut, "\n\t\t\t]" ); + fprintf( f_piDataOut, "\n\t\t}" ); + } + break; + case IVAS_PI_ISM_GAIN: + { + fprintf( f_piDataOut, "{\n" ); + fprintf( f_piDataOut, "\t\t\t\"gains\": [\n" ); + for ( n = 0; n < cur->data.ismGain.numObjects; n++ ) + { + if ( n != 0 ) + { + fprintf( f_piDataOut, ",\n" ); + } + fprintf( f_piDataOut, "\t\t\t\t%d", cur->data.ismGain.dB[n] ); + } + fprintf( f_piDataOut, "\n\t\t\t]" ); + fprintf( f_piDataOut, "\n\t\t}" ); + } + break; + case IVAS_PI_ISM_POSITION: + { + fprintf( f_piDataOut, "[\n" ); + for ( n = 0; n < cur->data.ismPosition.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.ismPosition.position[n].x, cur->data.ismPosition.position[n].y, cur->data.ismPosition.position[n].z ); + } + fprintf( f_piDataOut, "\n\t\t]" ); + } + break; + case IVAS_PI_ISM_DISTANCE_ATTENUATION: + { + fprintf( f_piDataOut, "[\n" ); + for ( n = 0; n < cur->data.ismAttenuation.numObjects; n++ ) + { + if ( n != 0 ) + { + fprintf( f_piDataOut, ",\n" ); + } + fprintf( f_piDataOut, "\t\t\t{\n\t\t\t\t\"ref_dist\": %f,\n\t\t\t\t\"max_dist\": %f,\n\t\t\t\t\"roll_off\": %f \n\t\t\t}", cur->data.ismAttenuation.distAtten[n].ref_dist, cur->data.ismAttenuation.distAtten[n].max_dist, cur->data.ismAttenuation.distAtten[n].roll ); + } + fprintf( f_piDataOut, "\n\t\t]" ); + } + break; + case IVAS_PI_ISM_DIRECTIVITY: + { + fprintf( f_piDataOut, "[\n" ); + for ( n = 0; n < cur->data.ismDirectivity.numObjects; n++ ) + { + if ( n != 0 ) + { + fprintf( f_piDataOut, ",\n" ); + } + fprintf( f_piDataOut, "\t\t\t{\n\t\t\t\t\"inner_ang\": %d,\n\t\t\t\t\"outer_ang\": %d,\n\t\t\t\t\"outer_att\": %f \n\t\t\t}", cur->data.ismDirectivity.directivity[n].innerConeAngle, cur->data.ismDirectivity.directivity[n].outerConeAngle, cur->data.ismDirectivity.directivity[n].outerAttenuationdB ); + } + fprintf( f_piDataOut, "\n\t\t]" ); + } + break; +#else case IVAS_PI_ISM_NUM: case IVAS_PI_ISM_ID: case IVAS_PI_ISM_GAIN: @@ -339,6 +440,7 @@ void IVAS_RTP_LogPiData( case IVAS_PI_ISM_POSITION: case IVAS_PI_ISM_DISTANCE_ATTENUATION: case IVAS_PI_ISM_DIRECTIVITY: +#endif case IVAS_PI_PI_LATENCY: case IVAS_PI_R_ISM_ID: case IVAS_PI_R_ISM_GAIN: diff --git a/lib_util/ivas_rtp_pi_data.c b/lib_util/ivas_rtp_pi_data.c index 8db9d41f9df241e317cdcf606e0fcc682c4a0a8c..0e7ceeb747087cab47119bc9db96cc4c1f517e6c 100644 --- a/lib_util/ivas_rtp_pi_data.c +++ b/lib_util/ivas_rtp_pi_data.c @@ -32,6 +32,18 @@ #include "ivas_error_utils.h" #include "ivas_rtp_internal.h" +#ifdef ISM_PI_DATA +#include + +#ifndef min +#define min( x, y ) ( ( x ) < ( y ) ? ( x ) : ( y ) ) +#endif + +#ifndef max +#define max( x, y ) ( ( x ) > ( y ) ? ( x ) : ( y ) ) +#endif + +#endif #ifdef IVAS_RTPDUMP @@ -154,6 +166,43 @@ static ivas_error packOrientation( const IVAS_PIDATA_GENERIC *piData, uint8_t *b return IVAS_ERR_OK; } +#ifdef ISM_PI_DATA +static ivas_error packISMOrientation( const IVAS_PIDATA_GENERIC *piData, uint8_t *buffer, uint32_t maxDataBytes, uint32_t *nBytesWritten ) +{ + uint32_t nBytes = 0; + const IVAS_PIDATA_ISM_ORIENTATION *orientation = (const IVAS_PIDATA_ISM_ORIENTATION *) piData; + uint16_t n; + *nBytesWritten = 0; + + if ( piData->size != sizeof( IVAS_PIDATA_ISM_ORIENTATION ) ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect size in Orientation PI data" ); + } + + if ( piData->piDataType != IVAS_PI_ISM_ORIENTATION ) + { + 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 * IVAS_MAX_NUM_OBJECTS + 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++] = (uint8_t) orientation->numObjects * 8; + for ( n = 0; n < orientation->numObjects; n++ ) + { + 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 ) ); + } + *nBytesWritten = nBytes; + return IVAS_ERR_OK; +} +#endif + static ivas_error unpackOrientation( const uint8_t *buffer, uint32_t numDataBytes, IVAS_PIDATA_GENERIC *piData ) { IVAS_PIDATA_ORIENTATION *orientation = (IVAS_PIDATA_ORIENTATION *) piData; @@ -173,6 +222,40 @@ static ivas_error unpackOrientation( const uint8_t *buffer, uint32_t numDataByte return IVAS_ERR_OK; } +#ifdef ISM_PI_DATA +static ivas_error unpackISMOrientation( const uint8_t *buffer, uint32_t numDataBytes, IVAS_PIDATA_GENERIC *piData ) +{ + IVAS_PIDATA_ISM_ORIENTATION *ism_orientation = (IVAS_PIDATA_ISM_ORIENTATION *) piData; + + /* Orientation data is 8 bytes */ + uint16_t n; + if ( numDataBytes % 8 != 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; + + for ( n = 0; n < ism_orientation->numObjects; n++ ) + { + 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] ) ); + } + for ( ; n < IVAS_MAX_NUM_OBJECTS; n++ ) + { + ism_orientation->orientation[n].w = 0.0f; + ism_orientation->orientation[n].x = 0.0f; + ism_orientation->orientation[n].y = 0.0f; + ism_orientation->orientation[n].z = 0.0f; + } + + return IVAS_ERR_OK; +} +#endif + static uint32_t getIndexTable( const float *table, uint32_t tableLength, float value ) { uint32_t idx = 0; @@ -477,6 +560,67 @@ static ivas_error unpackListenerPosition( const uint8_t *buffer, uint32_t numDat return IVAS_ERR_OK; } +#ifdef ISM_PI_DATA +static ivas_error packISMPosition( const IVAS_PIDATA_GENERIC *piData, uint8_t *buffer, uint32_t maxDataBytes, uint32_t *nBytesWritten ) +{ + uint32_t nBytes = 0, n; + 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 PI data" ); + } + + if ( piData->piDataType != IVAS_PI_ISM_POSITION ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect PI ID in ISM POSITION PI data" ); + } + + /* Position data is 6 bytes, header is 2 bytes */ + if ( maxDataBytes < 6 * IVAS_MAX_NUM_OBJECTS + 2 ) + { + return IVAS_ERROR( IVAS_ERR_RTP_INSUFFICIENT_OUTPUT_SIZE, "Insufficient space to pack ISM POSITION PI data" ); + } + + buffer[nBytes++] = ( ism_position->piDataType & MASK_5BIT ); /* PF/PM populated during final packing */ + buffer[nBytes++] = (uint8_t) ism_position->numObjects * 6; + for ( n = 0; n < ism_position->numObjects; n++ ) + { + nBytes = writeInt16( buffer, nBytes, ivasPayload_convertToQ15( ism_position->position[n].x / MAX_PI_POSITION_METERS ) ); + nBytes = writeInt16( buffer, nBytes, ivasPayload_convertToQ15( ism_position->position[n].y / MAX_PI_POSITION_METERS ) ); + nBytes = writeInt16( buffer, nBytes, ivasPayload_convertToQ15( ism_position->position[n].z / MAX_PI_POSITION_METERS ) ); + } + *nBytesWritten = nBytes; + return IVAS_ERR_OK; +} + +static ivas_error unpackISMPosition( const uint8_t *buffer, uint32_t numDataBytes, IVAS_PIDATA_GENERIC *piData ) +{ + uint16_t n; + IVAS_PIDATA_ISM_POSITION *ism_position = (IVAS_PIDATA_ISM_POSITION *) piData; + + /* Position data is 6 bytes */ + if ( numDataBytes % 6 != 0 ) + { + return IVAS_ERROR( IVAS_ERR_RTP_UNPACK_PI_DATA, "Incorrect size to unpack LISTENER POSITION PI data" ); + } + + ism_position->size = sizeof( IVAS_PIDATA_ISM_POSITION ); + ism_position->piDataType = IVAS_PI_ISM_POSITION; + ism_position->numObjects = (uint16_t) numDataBytes / 6; + + for ( n = 0; n < ism_position->numObjects; n++ ) + { + ism_position->position[n].x = FLOAT_FROM_Q15( readInt16( &buffer[6 * n] ) ) * MAX_PI_POSITION_METERS; + ism_position->position[n].y = FLOAT_FROM_Q15( readInt16( &buffer[6 * n + 2] ) ) * MAX_PI_POSITION_METERS; + ism_position->position[n].z = FLOAT_FROM_Q15( readInt16( &buffer[6 * n + 4] ) ) * MAX_PI_POSITION_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; @@ -629,6 +773,376 @@ static ivas_error unpackAudioFocusCommon( const uint8_t *buffer, uint32_t numDat return IVAS_ERR_OK; } +#ifdef ISM_PI_DATA +static ivas_error packISMNum( const IVAS_PIDATA_GENERIC *piData, uint8_t *buffer, uint32_t maxDataBytes, uint32_t *nBytesWritten ) +{ + uint32_t nBytes = 0; + const IVAS_PIDATA_ISM_NUM *ism_num = (const IVAS_PIDATA_ISM_NUM *) piData; + + *nBytesWritten = 0; + + if ( piData->size != sizeof( IVAS_PIDATA_ISM_NUM ) ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect size in ISM_NUM PI data" ); + } + + if ( piData->piDataType != IVAS_PI_ISM_NUM ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect PI ID in ISM_NUM PI data" ); + } + + /* ISM_NUM data is 1 bytes, header is 2 bytes */ + if ( maxDataBytes < 1 + 2 ) + { + return IVAS_ERROR( IVAS_ERR_RTP_INSUFFICIENT_OUTPUT_SIZE, "Insufficient space to pack ISM_NUM PI data" ); + } + + buffer[nBytes++] = ( ism_num->piDataType & MASK_5BIT ); /* PF/PM populated during final packing */ + buffer[nBytes++] = 1; + buffer[nBytes++] = ( ( ism_num->numObjects - 1 ) & MASK_2BIT ) << 6; + *nBytesWritten = nBytes; + return IVAS_ERR_OK; +} + +static ivas_error unpackISMNum( const uint8_t *buffer, uint32_t numDataBytes, IVAS_PIDATA_GENERIC *piData ) +{ + IVAS_PIDATA_ISM_NUM *ism_num = (IVAS_PIDATA_ISM_NUM *) piData; + uint8_t byte; + + /* ISM_NUM data is 1 bytes */ + if ( numDataBytes != 1 ) + { + return IVAS_ERROR( IVAS_ERR_RTP_UNPACK_PI_DATA, "Incorrect size to unpack ISM_NUM PI data" ); + } + + ism_num->size = sizeof( IVAS_PIDATA_ISM_NUM ); + ism_num->piDataType = IVAS_PI_ISM_NUM; + + byte = buffer[0]; + ism_num->numObjects = ( ( byte >> 6 ) & MASK_2BIT ) + 1; + + return IVAS_ERR_OK; +} +static ivas_error packISMID( const IVAS_PIDATA_GENERIC *piData, uint8_t *buffer, uint32_t maxDataBytes, uint32_t *nBytesWritten ) +{ + uint32_t nBytes = 0, n; + const IVAS_PIDATA_ISM_ID *ism_id = (const IVAS_PIDATA_ISM_ID *) piData; + + *nBytesWritten = 0; + + if ( piData->size > sizeof( IVAS_PIDATA_ISM_ID ) ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect size in ISM_ID PI data" ); + } + + if ( piData->piDataType != IVAS_PI_ISM_ID ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect PI ID in ISM_ID PI data" ); + } + + /* ISM_ID data is 1 byte per object, header is 2 bytes */ + if ( maxDataBytes < 1 * IVAS_MAX_NUM_OBJECTS + 2 ) + { + return IVAS_ERROR( IVAS_ERR_RTP_INSUFFICIENT_OUTPUT_SIZE, "Insufficient space to pack ISM_NUM PI data" ); + } + + buffer[nBytes++] = ( ism_id->piDataType & MASK_5BIT ); /* PF/PM populated during final packing */ + buffer[nBytes++] = (uint8_t) ism_id->numObjects; + /* Pack ID for each object */ + for ( n = 0; n < ism_id->numObjects; n++ ) + { + buffer[nBytes++] = ( ism_id->id[n] & MASK_8BIT ); + } + *nBytesWritten = nBytes; + return IVAS_ERR_OK; +} + +static ivas_error unpackISMID( const uint8_t *buffer, uint32_t numDataBytes, IVAS_PIDATA_GENERIC *piData ) +{ + uint32_t n; + IVAS_PIDATA_ISM_ID *ism_id = (IVAS_PIDATA_ISM_ID *) piData; + + /* ISM_ID data is 1 byte per object */ + if ( numDataBytes > IVAS_MAX_NUM_OBJECTS ) + { + return IVAS_ERROR( IVAS_ERR_RTP_UNPACK_PI_DATA, "Incorrect size to unpack ISM_ID PI data" ); + } + + ism_id->size = sizeof( IVAS_PIDATA_ISM_ID ); + ism_id->piDataType = IVAS_PI_ISM_ID; + ism_id->numObjects = (uint16_t) numDataBytes; + + /* Unpack ID for each object (1 byte each) */ + for ( n = 0; n < ism_id->numObjects; n++ ) + { + ism_id->id[n] = buffer[n]; + } + for ( ; n < IVAS_MAX_NUM_OBJECTS; n++ ) + { + ism_id->id[n] = 0; /* Initializing to 0, although there might be another object with this ID */ + } + + return IVAS_ERR_OK; +} + +static ivas_error packISMGain( const IVAS_PIDATA_GENERIC *piData, uint8_t *buffer, uint32_t maxDataBytes, uint32_t *nBytesWritten ) +{ + uint32_t nBytes = 0, n, idx; + int16_t gain; + const IVAS_PIDATA_ISM_GAIN *ism_gain = (const IVAS_PIDATA_ISM_GAIN *) piData; + + *nBytesWritten = 0; + + if ( piData->size > sizeof( IVAS_PIDATA_ISM_GAIN ) ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect size in ISM_GAIN PI data" ); + } + + if ( piData->piDataType != IVAS_PI_ISM_GAIN ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect PI ID in ISM_GAIN PI data" ); + } + + /* ISM_GAIN data is 1 byte per object, header is 2 bytes */ + if ( maxDataBytes < 1 * IVAS_MAX_NUM_OBJECTS + 2 ) + { + return IVAS_ERROR( IVAS_ERR_RTP_INSUFFICIENT_OUTPUT_SIZE, "Insufficient space to pack ISM_GAIN PI data" ); + } + + buffer[nBytes++] = ( ism_gain->piDataType & MASK_5BIT ); /* PF/PM populated during final packing */ + buffer[nBytes++] = (uint8_t) ism_gain->numObjects; + /* Pack ID for each object */ + for ( n = 0; n < ism_gain->numObjects; n++ ) + { + gain = (int16_t) ism_gain->dB[n]; + idx = min( -gain, 97 ); + if ( gain > 0 ) + { + idx += 97; + } + + buffer[nBytes++] = ( idx & MASK_7BIT ) << 1; + } + *nBytesWritten = nBytes; + return IVAS_ERR_OK; +} + +static ivas_error unpackISMGain( const uint8_t *buffer, uint32_t numDataBytes, IVAS_PIDATA_GENERIC *piData ) +{ + uint32_t n, idx; + IVAS_PIDATA_ISM_GAIN *ism_gain = (IVAS_PIDATA_ISM_GAIN *) piData; + + /* ISM_GAIN data is 1 byte per object */ + if ( numDataBytes > IVAS_MAX_NUM_OBJECTS ) + { + return IVAS_ERROR( IVAS_ERR_RTP_UNPACK_PI_DATA, "Incorrect size to unpack ISM_GAIN PI data" ); + } + + ism_gain->size = sizeof( IVAS_PIDATA_ISM_GAIN ); + ism_gain->piDataType = IVAS_PI_ISM_GAIN; + ism_gain->numObjects = (uint16_t) numDataBytes; + + /* Unpack ID for each object (1 byte each) */ + for ( n = 0; n < ism_gain->numObjects; n++ ) + { + idx = ( buffer[n] ) >> 1; + /* negative gains*/ + if ( idx < 97 ) + { + ism_gain->dB[n] = -(int8_t) ( idx ); + } + /* Set to min for muting, to be interpreted as -Inf */ + else if ( idx == 97 ) + { + ism_gain->dB[n] = -128; + } + /* postive gains */ + else if ( idx < 101 ) + { + ism_gain->dB[n] = (int8_t) idx - 97; + } + else + { + return IVAS_ERROR( IVAS_ERR_RTP_UNPACK_PI_DATA, "Incorrect index for ISM_GAIN PI data" ); + } + } + for ( ; n < IVAS_MAX_NUM_OBJECTS; n++ ) + { + ism_gain->dB[n] = 0; /* Set to default */ + } + return IVAS_ERR_OK; +} + +static ivas_error packISMDistanceAttenuation( const IVAS_PIDATA_GENERIC *piData, uint8_t *buffer, uint32_t maxDataBytes, uint32_t *nBytesWritten ) +{ + uint32_t nBytes = 0, n; + const IVAS_PIDATA_ISM_ATTENUATION *ism_att = (const IVAS_PIDATA_ISM_ATTENUATION *) piData; + uint32_t lWord; + + *nBytesWritten = 0; + + if ( piData->size > sizeof( IVAS_PIDATA_ISM_ATTENUATION ) ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect size in ISM_DISTANCE_ATTENUATION PI data" ); + } + + if ( piData->piDataType != IVAS_PI_ISM_DISTANCE_ATTENUATION ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect PI ID in ISM_DISTANCE_ATTENUATION PI data" ); + } + + /* ISM_DISTANCE_ATTENUATION data is 3 bytes per object, header is 2 bytes */ + if ( maxDataBytes > 3 * IVAS_MAX_NUM_OBJECTS + 2 ) + { + return IVAS_ERROR( IVAS_ERR_RTP_INSUFFICIENT_OUTPUT_SIZE, "Insufficient space to pack ISM_DISTANCE_ATTENUATION PI data" ); + } + + buffer[nBytes++] = ( ism_att->piDataType & MASK_5BIT ); /* PF/PM populated during final packing */ + buffer[nBytes++] = (uint8_t) ism_att->numObjects * 3; + /* Pack ID for each object */ + for ( n = 0; n < ism_att->numObjects; n++ ) + { + if ( ism_att->distAtten[n].ref_dist < 0 || ism_att->distAtten[n].max_dist < 0 || ism_att->distAtten[n].roll < 0 ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect DISTANCE ATTENUATION data" ); + } + lWord = (uint32_t) ( min( (uint16_t) ( ism_att->distAtten[n].ref_dist * 10.0f + 0.5f ) - 1, 63 ) << 18 ); + lWord |= (uint32_t) ( min( (uint16_t) ( ism_att->distAtten[n].max_dist + 0.5f ) - 1, 63 ) << 12 ); + lWord |= (uint32_t) ( min( (uint16_t) ( ism_att->distAtten[n].roll * 10.0f + 0.5f ), 40 ) << 6 ); + + buffer[nBytes++] = ( lWord >> 16 ) & MASK_8BIT; + buffer[nBytes++] = ( lWord >> 8 ) & MASK_8BIT; + buffer[nBytes++] = lWord & MASK_8BIT; + } + *nBytesWritten = nBytes; + return IVAS_ERR_OK; +} + +static ivas_error unpackISMDistanceAttenuation( const uint8_t *buffer, uint32_t numDataBytes, IVAS_PIDATA_GENERIC *piData ) +{ + uint32_t n, lWord; + IVAS_PIDATA_ISM_ATTENUATION *ism_att = (IVAS_PIDATA_ISM_ATTENUATION *) piData; + + /* ISM_DISTANCE_ATTENUATION data is 3 bytes per object */ + if ( numDataBytes % 3 != 0 ) + { + return IVAS_ERROR( IVAS_ERR_RTP_UNPACK_PI_DATA, "Incorrect size to unpack ISM_DISTANCE_ATTENUATION PI data" ); + } + + ism_att->size = sizeof( IVAS_PIDATA_ISM_ATTENUATION ); + ism_att->piDataType = IVAS_PI_ISM_DISTANCE_ATTENUATION; + ism_att->numObjects = (uint16_t) numDataBytes / 3; + + /* Unpack attenuation for each object (3 bytes each) */ + for ( n = 0; n < ism_att->numObjects; n++ ) + { + lWord = ( buffer[3 * n] ) << 16; + lWord |= ( buffer[3 * n + 1] ) << 8; + lWord |= buffer[3 * n + 2]; + + ism_att->distAtten[n].ref_dist = ( ( ( lWord >> 18 ) & MASK_6BIT ) + 1 ) / 10.0f; + ism_att->distAtten[n].max_dist = (float) ( ( lWord >> 12 ) & MASK_6BIT ) + 1; + ism_att->distAtten[n].roll = ( ( lWord >> 6 ) & MASK_6BIT ) / 10.0f; + } + for ( ; n < IVAS_MAX_NUM_OBJECTS; n++ ) + { + ism_att->distAtten[n].ref_dist = 1.0f; /* Set to default */ + ism_att->distAtten[n].max_dist = 16.0f; /* Set to default */ + ism_att->distAtten[n].roll = 1.0f; /* Set to default */ + } + return IVAS_ERR_OK; +} +static ivas_error packISMDirectivity( const IVAS_PIDATA_GENERIC *piData, uint8_t *buffer, uint32_t maxDataBytes, uint32_t *nBytesWritten ) +{ + uint32_t nBytes = 0, n; + const IVAS_PIDATA_ISM_DIRECTIVITY *ism_directivity = (const IVAS_PIDATA_ISM_DIRECTIVITY *) piData; + uint16_t word, idx; + + *nBytesWritten = 0; + + if ( piData->size > sizeof( IVAS_PIDATA_ISM_DIRECTIVITY ) ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect size in ISM_DIRECTIVITY PI data" ); + } + + if ( piData->piDataType != IVAS_PI_ISM_DIRECTIVITY ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect PI ID in ISM_DIRECTIVITY PI data" ); + } + + /* ISM_DIRECTIVITY data is 2 bytes per object, header is 2 bytes */ + if ( maxDataBytes > 2 * IVAS_MAX_NUM_OBJECTS + 2 ) + { + return IVAS_ERROR( IVAS_ERR_RTP_INSUFFICIENT_OUTPUT_SIZE, "Insufficient space to pack ISM_DIRECTIVITY PI data" ); + } + + buffer[nBytes++] = ( ism_directivity->piDataType & MASK_5BIT ); /* PF/PM populated during final packing */ + buffer[nBytes++] = (uint8_t) ism_directivity->numObjects * 2; + /* Pack directivity for each object */ + for ( n = 0; n < ism_directivity->numObjects; n++ ) + { + word = (uint16_t) ( min( ism_directivity->directivity[n].innerConeAngle / 15, 24 ) << 11 ); + word |= (uint16_t) ( min( ism_directivity->directivity[n].outerConeAngle / 15, 24 ) << 6 ); + + idx = 0; + /* For outer attenuation < -90 dB, idx = 0, which corresponds to -Inf (muting) */ + if ( ism_directivity->directivity[n].outerAttenuationdB >= -90.0f ) + { + idx = 32 - (uint16_t) ( -ism_directivity->directivity[n].outerAttenuationdB / 3.0f + 0.5f ); + } + word |= (uint16_t) ( min( idx, 31 ) << 1 ); + + buffer[nBytes++] = ( word >> 8 ) & MASK_8BIT; + buffer[nBytes++] = word & MASK_8BIT; + } + *nBytesWritten = nBytes; + return IVAS_ERR_OK; +} + +static ivas_error unpackISMDirectivity( const uint8_t *buffer, uint32_t numDataBytes, IVAS_PIDATA_GENERIC *piData ) +{ + uint32_t n; + uint16_t word, idx; + IVAS_PIDATA_ISM_DIRECTIVITY *ism_directivity = (IVAS_PIDATA_ISM_DIRECTIVITY *) piData; + + /* ISM_DIRECTIVITY data is 2 bytes per object */ + if ( numDataBytes % 2 != 0 ) + { + return IVAS_ERROR( IVAS_ERR_RTP_UNPACK_PI_DATA, "Incorrect size to unpack ISM_DIRECTIVITY PI data" ); + } + + ism_directivity->size = sizeof( IVAS_PIDATA_ISM_DIRECTIVITY ); + ism_directivity->piDataType = IVAS_PI_ISM_DIRECTIVITY; + ism_directivity->numObjects = (uint16_t) numDataBytes / 2; + + /* Unpack directivity for each object (2 bytes each) */ + for ( n = 0; n < ism_directivity->numObjects; n++ ) + { + word = ( buffer[2 * n] ) << 8; + word |= ( buffer[2 * n + 1] ); + + ism_directivity->directivity[n].innerConeAngle = ( ( word >> 11 ) & MASK_5BIT ) * 15; + ism_directivity->directivity[n].outerConeAngle = ( ( word >> 6 ) & MASK_5BIT ) * 15; + idx = ( word >> 1 ) & MASK_5BIT; + + if ( idx == 0 ) + { + ism_directivity->directivity[n].outerAttenuationdB = -32768.0f; /* corresponds to muting */ + } + else + { + ism_directivity->directivity[n].outerAttenuationdB = -3.0f * ( 31 - ( ( word >> 1 ) & MASK_5BIT ) ); + } + } + for ( ; n < IVAS_MAX_NUM_OBJECTS; n++ ) + { + ism_directivity->directivity[n].innerConeAngle = 360; /* Set to default */ + ism_directivity->directivity[n].outerConeAngle = 360; /* Set to default */ + ism_directivity->directivity[n].outerAttenuationdB = 0; /* Set to default */ + } + return IVAS_ERR_OK; +} +#endif #endif /* RTP_S4_251135_CR26253_0016_REV1 */ @@ -642,14 +1156,24 @@ static const PACK_PI_FN packPiDataFuntions[IVAS_PI_MAX_ID] = { packAudioDescription, /* AUDIO_DESCRIPTION */ #else packUnsupportedData, /* AUDIO_DESCRIPTION */ -#endif /* RTP_S4_251135_CR26253_0016_REV1 */ - packUnsupportedData, /* ISM_NUM */ - packUnsupportedData, /* ISM_ID */ - packUnsupportedData, /* ISM_GAIN */ - packUnsupportedData, /* ISM_ORIENTATION */ - packUnsupportedData, /* ISM_POSITION */ - packUnsupportedData, /* ISM_DISTANCE_ATTENUATION */ - packUnsupportedData, /* ISM_DIRECTIVITY */ +#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 */ + packISMDistanceAttenuation, /* ISM_DISTANCE_ATTENUATION */ + packISMDirectivity, /* ISM_DIRECTIVITY */ +#else + packUnsupportedData, /* ISM_NUM */ + packUnsupportedData, /* ISM_ID */ + packUnsupportedData, /* ISM_GAIN */ + packUnsupportedData, /* ISM_ORIENTATION */ + packUnsupportedData, /* ISM_POSITION */ + packUnsupportedData, /* ISM_DISTANCE_ATTENUATION */ + packUnsupportedData, /* ISM_DIRECTIVITY */ +#endif #ifdef RTP_S4_251135_CR26253_0016_REV1 packDiegetic, /* DIEGETIC_TYPE */ #else @@ -702,6 +1226,15 @@ static const UNPACK_PI_FN unpackPiDataFuntions[IVAS_PI_MAX_ID] = { #else unpackUnsupportedData, /* AUDIO_DESCRIPTION */ #endif +#ifdef ISM_PI_DATA + unpackISMNum, /* ISM_NUM */ + unpackISMID, /* ISM_ID */ + unpackISMGain, /* ISM_GAIN */ + unpackISMOrientation, /* ISM_ORIENTATION */ + unpackISMPosition, /* ISM_POSITION */ + unpackISMDistanceAttenuation, /* ISM_DISTANCE_ATTENUATION */ + unpackISMDirectivity, /* ISM_DIRECTIVITY */ +#else unpackUnsupportedData, /* ISM_NUM */ unpackUnsupportedData, /* ISM_ID */ unpackUnsupportedData, /* ISM_GAIN */ @@ -709,6 +1242,7 @@ static const UNPACK_PI_FN unpackPiDataFuntions[IVAS_PI_MAX_ID] = { unpackUnsupportedData, /* ISM_POSITION */ unpackUnsupportedData, /* ISM_DISTANCE_ATTENUATION */ unpackUnsupportedData, /* ISM_DIRECTIVITY */ +#endif #ifdef RTP_S4_251135_CR26253_0016_REV1 unpackDiegetic, /* DIEGETIC_TYPE */ #else @@ -845,5 +1379,4 @@ const float mapAbsorbtion[1u << NBITS_ABS] = { 0.0800f, 0.1656f, 0.3430f, 0.7101f }; - #endif /* IVAS_RTPDUMP */ diff --git a/lib_util/ivas_rtp_pi_data.h b/lib_util/ivas_rtp_pi_data.h index a6292369e16f8c2106f18f1e51c81636f79f102d..09944506349d7ca7eacf2ac22ce76d3ec744f4bd 100644 --- a/lib_util/ivas_rtp_pi_data.h +++ b/lib_util/ivas_rtp_pi_data.h @@ -214,32 +214,44 @@ typedef struct /* ISM ID */ typedef struct { - size_t size; /* sizeof(IVAS_PIDATA_ISM_ID) */ - uint32_t piDataType; /* IVAS_PI_ISM_ID */ + size_t size; /* sizeof(IVAS_PIDATA_ISM_ID) */ + uint32_t piDataType; /* IVAS_PI_ISM_ID */ +#ifdef ISM_PI_DATA + uint16_t numObjects; /* number of objects */ +#endif uint8_t id[IVAS_MAX_NUM_OBJECTS]; /* 8-bit ISM id of object */ } IVAS_PIDATA_ISM_ID; /* ISM gain */ typedef struct { - size_t size; /* sizeof(IVAS_PIDATA_ISM_GAIN) */ - uint32_t piDataType; /* IVAS_PI_ISM_GAIN */ + size_t size; /* sizeof(IVAS_PIDATA_ISM_GAIN) */ + uint32_t piDataType; /* IVAS_PI_ISM_GAIN */ +#ifdef ISM_PI_DATA + uint16_t numObjects; /* number of objects */ +#endif int8_t dB[IVAS_MAX_NUM_OBJECTS]; /* ISM gain in dB per object [-96, +3] */ } IVAS_PIDATA_ISM_GAIN; /* ISM orientation */ typedef struct { - size_t size; /* sizeof(IVAS_PIDATA_ISM_ORIENTATION) */ - uint32_t piDataType; /* IVAS_PI_ISM_ORIENTATION */ + size_t size; /* sizeof(IVAS_PIDATA_ISM_ORIENTATION) */ + uint32_t piDataType; /* IVAS_PI_ISM_ORIENTATION */ +#ifdef ISM_PI_DATA + uint16_t numObjects; /* number of objects */ +#endif IVAS_QUATERNION orientation[IVAS_MAX_NUM_OBJECTS]; /* Orientation of audio objects in ISM(s) */ } IVAS_PIDATA_ISM_ORIENTATION; /* ISM position */ typedef struct { - size_t size; /* sizeof(IVAS_PIDATA_ISM_POSITION) */ - uint32_t piDataType; /* IVAS_PI_ISM_POSITION */ + size_t size; /* sizeof(IVAS_PIDATA_ISM_POSITION) */ + uint32_t piDataType; /* IVAS_PI_ISM_POSITION */ +#ifdef ISM_PI_DATA + uint16_t numObjects; /* number of objects */ +#endif IVAS_COORDINATE position[IVAS_MAX_NUM_OBJECTS]; /* Position of audio objects in ISM(s) */ } IVAS_PIDATA_ISM_POSITION; @@ -257,8 +269,11 @@ typedef struct typedef struct { - size_t size; /* sizeof(IVAS_PIDATA_ISM_ATTENUATION) */ - uint32_t piDataType; /* IVAS_PI_ISM_DISTANCE_ATTENUATION */ + size_t size; /* sizeof(IVAS_PIDATA_ISM_ATTENUATION) */ + uint32_t piDataType; /* IVAS_PI_ISM_DISTANCE_ATTENUATION */ +#ifdef ISM_PI_DATA + uint16_t numObjects; /* number of objects */ +#endif IVAS_DIST_ATTEN distAtten[IVAS_MAX_NUM_OBJECTS]; /* Distance attenuation of audio objects */ } IVAS_PIDATA_ISM_ATTENUATION; @@ -276,8 +291,11 @@ typedef struct typedef struct { - size_t size; /* sizeof(IVAS_PIDATA_ISM_DIRECTIVITY) */ - uint32_t piDataType; /* IVAS_PI_ISM_DIRECTIVITY */ + size_t size; /* sizeof(IVAS_PIDATA_ISM_DIRECTIVITY) */ + uint32_t piDataType; /* IVAS_PI_ISM_DIRECTIVITY */ +#ifdef ISM_PI_DATA + uint16_t numObjects; /* number of objects */ +#endif IVAS_ISM_DIRECTIVITY directivity[IVAS_MAX_NUM_OBJECTS]; /* Directivity of audio objects */ } IVAS_PIDATA_ISM_DIRECTIVITY; @@ -337,7 +355,6 @@ typedef struct IVAS_COORDINATE position; /* Position of audio objects in ISM(s) */ } IVAS_PIDATA_LISTENER_POSITION; - /* Dynamic Audio Suppression describes receiver’s preference with respect to the * type of audio content that should be enhanced and the amount of suppression to * be applied to the background noise diff --git a/tests/rtp/ivasrtp.py b/tests/rtp/ivasrtp.py index b09333fc46c5b2797607efb6d11b5078ec033924..b336fec5d1160d874dd86d024ade2d070600618c 100644 --- a/tests/rtp/ivasrtp.py +++ b/tests/rtp/ivasrtp.py @@ -389,6 +389,46 @@ class ACOUSTIC_ENVIRONMENT: abscoeff: tuple[float, float, float, float, float, float] = () +@dataclass +class ISM_NUM: + num: int = 1 + +@dataclass +class ISM_ID: + ids: list[int] + +@dataclass +class ISM_GAIN: + gains: list[int] + +@dataclass +class ISM_ORIENTATION: + orientations: list[ORIENTATION] + +@dataclass +class ISM_POSITION: + positions: list[POSITION] + +@dataclass +class DISTANCE_ATTENUATION: + ref_dist: float = 1.0 + max_dist: int = 10 + roll_off: float = 1.0 + +@dataclass +class ISM_DISTANCE_ATTENUATION: + distance_attenuations: list[DISTANCE_ATTENUATION] + +@dataclass +class DIRECTIVITY: + inner_ang: int = 360 + outer_ang: int = 0 + outer_att: int = 0 + +@dataclass +class ISM_DIRECTIVITY: + directivities: list[DIRECTIVITY] + @dataclass class AUDIO_FOCUS: direction: Optional[ORIENTATION] = None @@ -402,7 +442,7 @@ class PIDATA: data: any = None -MAX_PACKED_PI_SIZE = 32 +MAX_PACKED_PI_SIZE = 48 ivasBitrates = [ 13200, 16400, @@ -581,6 +621,12 @@ roomDimensionValue = [ 90.51, ] absorptionCoeffValues = [0.0800, 0.1656, 0.3430, 0.7101] +ismGains = list(range(0, -97, -1)) + [-float("inf")] + list(range(1, 4)) +refDistances = [round(x * 0.1, 1) for x in range(1, 65)] +maxDistances = list(range(1,65)) +rolloffFactors = [round(x * 0.1, 1) for x in range(0, 41)] +innerOuterAngles = list(range(0,361,15)) +outerAttenuations = [-float("inf")] + list(range(-90,1,3)) codedFormats = list(FORMATS) codedSubFormats = list(SUBFORMATS) PiTypeNames = list(PIDATAS) @@ -923,6 +969,103 @@ def packAudioFocus(bitstrm: BitStream, data: any): bitstrm.append(f"uint:4={level}") bitstrm.append(f"uint:4=0") +def unpackISMNum(bitstrm: ConstBitStream, piSize: int) -> ISM_NUM: + assert piSize == 1, "Incorrect PI Data Size for ISM_NUM" + numISM = bitstrm.read(2).uint + 1 + bitstrm.bytealign() + return ISM_NUM(num=numISM) + +def packISMNum(bitstrm: BitStream, data: any): + assert type(data) == ISM_NUM, "Data of type ISM_NUM is expected" + ism_num = cast(ISM_NUM, data) + assert ism_num.num <= 4, "Maximum 4 objects" + bitstrm.append(f'uint:2={ism_num.num-1}') + bitstrm.append(f'uint:6=0') + +def unpackISMID(bitstrm: ConstBitStream, piSize: int) -> ISM_ID: + assert piSize == 1 or piSize == 2 or piSize == 3 or piSize == 4, "Incorrect PI Data Size for ISM_ID" + IsmID = list() + for _ in range(piSize): + IsmID.append(bitstrm.read(8).uint+1) + return ISM_ID(ids=IsmID) + +def packISMID(bitstrm: BitStream, data: any): + assert type(data) == ISM_ID, "Data of type ISM_ID is expected" + ism_id = cast(ISM_ID, data) + assert len(ism_id.ids) <= 4, "Maximum 4 objects" + for id in ism_id.ids: + bitstrm.append(f'uint:8={id}') + +def unpackISMGain(bitstrm: ConstBitStream, piSize: int) -> ISM_GAIN: + assert piSize == 1 or piSize == 2 or piSize == 3 or piSize == 4, "Incorrect PI Data Size for ISM_GAIN" + IsmGain = list() + for _ in range(piSize): + IsmGain.append(bitstrm.read(7).uint) + bitstrm.bytealign() + return ISM_GAIN(gains=IsmGain) + +def packISMGain(bitstrm: BitStream, data: any): + assert type(data) == ISM_GAIN, "Data of type ISM_GAIN is expected" + ism_gain = cast(ISM_GAIN, data) + assert len(ism_gain.gains) <= 4, "Maximum 4 objects" + for gain in ism_gain.gains: + gain_idx = getListIndex(ismGains, gain) + bitstrm.append(f'uint:7={gain_idx}') + bitstrm.append(f'uint:1=0') + +def unpackISMDistanceAttenuation(bitstrm: ConstBitStream, piSize: int) -> ISM_DISTANCE_ATTENUATION: + ref_dist = None + max_dist = None + roll_off = None + assert piSize == 1*3 or piSize == 2*3 or piSize == 3*3 or piSize == 4*3, "Incorrect PI Data Size for ISM_DISTANCE_ATTENUATION" + ism_distance_attenutation = list() + for _ in range(piSize): + ref_dist = bitstrm.read(6).uint + max_dist = bitstrm.read(6).uint + roll_off = bitstrm.read(6).uint + ism_distance_attenutation.append(DISTANCE_ATTENUATION(ref_dist=ref_dist, max_dist=max_dist, roll_off=roll_off)) + bitstrm.bytealign() + return ISM_DISTANCE_ATTENUATION(distance_attenuations=ism_distance_attenutation) + +def packISMDistanceAttenuation(bitstrm: BitStream, data: any): + assert type(data) == list, "Data of type list is expected" + + for att in cast(list, data): + assert type(att) == DISTANCE_ATTENUATION, "Data of type list[DISTANCE_ATTENUATION] is expected" + ref_dist_idx = getListIndex(refDistances, att.ref_dist) + max_dist_idx = getListIndex(maxDistances, att.max_dist) + roll_off_idx = getListIndex(rolloffFactors, att.roll_off) + bitstrm.append(f'uint:6={ref_dist_idx}') + bitstrm.append(f'uint:6={max_dist_idx}') + bitstrm.append(f'uint:6={roll_off_idx}') + bitstrm.append(f'uint:6=0') + +def unpackISMDirectivity(bitstrm: ConstBitStream, piSize: int) -> list[DISTANCE_ATTENUATION]: + inner_ang = None + outer_ang = None + outer_att = None + assert piSize == 1*2 or piSize == 2*2 or piSize == 3*2 or piSize == 4*2, "Incorrect PI Data Size for ISM_DISTANCE_ATTENUATION" + directivities = list() + for _ in range(piSize): + inner_ang = bitstrm.read(5).uint + outer_ang = bitstrm.read(5).uint + outer_att = bitstrm.read(5).uint + directivities.append(DIRECTIVITY(inner_ang=inner_ang, outer_ang=outer_ang, outer_att=outer_att)) + bitstrm.bytealign() + return directivities + +def packISMDirectivity(bitstrm: BitStream, data: any): + assert type(data) == list, "Data of type ISM_DIRECTIVITY is expected" + + for dir in cast(list, data): + assert type(dir) == DIRECTIVITY, "Orientation PI Data expects a data of type list[DIRECTIVITY]" + inner_ang_idx = getListIndex(innerOuterAngles, dir.inner_ang) + outer_ang_idx = getListIndex(innerOuterAngles, dir.outer_ang) + outer_att_idx = getListIndex(outerAttenuations, dir.outer_att) + bitstrm.append(f'uint:5={inner_ang_idx}') + bitstrm.append(f'uint:5={outer_ang_idx}') + bitstrm.append(f'uint:5={outer_att_idx}') + bitstrm.append(f'uint:1=0') PIDataUnpacker = [ unpackOrientation, # SCENE_ORIENTATION, @@ -930,13 +1073,13 @@ PIDataUnpacker = [ unpackOrientation, # DEVICE_ORIENTATION_UNCOMPENSATED unpackAcousticEnv, # ACOUSTIC_ENVIRONMENT unpackAudioDescription, # AUDIO_DESCRIPTION - unpackUnsupported, # ISM_NUM - unpackUnsupported, # ISM_ID - unpackUnsupported, # ISM_GAIN + unpackISMNum, # ISM_NUM + unpackISMID, # ISM_ID + unpackISMGain, # ISM_GAIN unpackOrientations, # ISM_ORIENTATION unpackPositions, # ISM_POSITION - unpackUnsupported, # ISM_DISTANCE_ATTENUATION - unpackUnsupported, # ISM_DIRECTIVITY + unpackISMDistanceAttenuation, # ISM_DISTANCE_ATTENUATION + unpackISMDirectivity, # ISM_DIRECTIVITY unpackDiegetic, # DIEGETIC_TYPE unpackDAS, # DYNAMIC_AUDIO_SUPPRESSION_INDICATION unpackAudioFocus, # AUDIO_FOCUS_INDICATION @@ -965,13 +1108,13 @@ PIDataPacker = [ packOrientation, # DEVICE_ORIENTATION_UNCOMPENSATED packAcousticEnv, # ACOUSTIC_ENVIRONMENT packAudioDescription, # AUDIO_DESCRIPTION - packUnsupported, # ISM_NUM - packUnsupported, # ISM_ID - packUnsupported, # ISM_GAIN + packISMNum, # ISM_NUM + packISMID, # ISM_ID + packISMGain, # ISM_GAIN packOrientations, # ISM_ORIENTATION packPositions, # ISM_POSITION - packUnsupported, # ISM_DISTANCE_ATTENUATION - packUnsupported, # ISM_DIRECTIVITY + packISMDistanceAttenuation, # ISM_DISTANCE_ATTENUATION + packISMDirectivity, # ISM_DIRECTIVITY packDiegetic, # DIEGETIC_TYPE packDAS, # DYNAMIC_AUDIO_SUPPRESSION_INDICATION packAudioFocus, # AUDIO_FOCUS_INDICATION diff --git a/tests/rtp/test_rtp.py b/tests/rtp/test_rtp.py index 2a37f01103e7cc8c82cced8001460c8f5d65344d..a8f36c852120fabb59f81a14c44fb47c26d742c0 100644 --- a/tests/rtp/test_rtp.py +++ b/tests/rtp/test_rtp.py @@ -261,6 +261,14 @@ def generatePiData(startTs: int, endTs: int) -> dict: ) someAcousticEnvList = [someAcousticEnvAEID, someAcousticEnvLR, someAcousticEnvERLR] + 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=[int(random.randint(-96,3)) for _ in range(num_ism)]) + 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)] + someISMDistanceAttenuations = lambda num_ism : [DISTANCE_ATTENUATION(ref_dist=random.randint(1,64)/10.0, max_dist=random.randint(1,64), roll_off=random.randint(0,40)/10.0) for _ in range(num_ism)] + someISMDirectivities = lambda num_ism : [DIRECTIVITY(inner_ang=random.randint(0,24)*15, outer_ang=random.randint(0,24)*15, outer_att=random.randint(-30,0)*3) for _ in range(num_ism)] + for ts in range(startTs, endTs, 320): pidata = dict() pidata["SCENE_ORIENTATION"] = someOrientation() @@ -274,6 +282,13 @@ def generatePiData(startTs: int, endTs: int) -> dict: pidata["AUDIO_DESCRIPTION"] = [someDesc() for n in range(random.randint(1, 5))] pidata["DIEGETIC_TYPE"] = someDIG() pidata["ACOUSTIC_ENVIRONMENT"] = random.choice(someAcousticEnvList)() + pidata["ISM_NUM"] = someNumISM() + pidata["ISM_ID"] = someISMIds(pidata["ISM_NUM"].num) + 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_DISTANCE_ATTENUATION"] = someISMDistanceAttenuations(pidata["ISM_NUM"].num) + pidata["ISM_DIRECTIVITY"] = someISMDirectivities(pidata["ISM_NUM"].num) data[str(ts)] = pidata return data @@ -370,6 +385,26 @@ def isEqualAudioFocus(ref: AUDIO_FOCUS, dut: AUDIO_FOCUS): ), "Audio Focus PI Data mismatch in direction z" assert ref.level == dut.level, "Audio Focus PI Data mismatch in level" +def isEqualISMNum(ref: ISM_NUM, dut: ISM_NUM): + assert ref.num == dut.num, "ISM NUM PI Data mismatch" + +def isEqualISMID(ref: ISM_ID, dut: ISM_ID): + for r, d in zip(ref.ids, dut.ids): + assert r == d, f"ISM ID PI Data mismatch {r} != {d}" + +def isEqualISMGain(ref: ISM_GAIN, dut: ISM_GAIN): + for r, d in zip(ref.gains, dut.gains): + assert r == d, f"ISM GAIN PI Data mismatch {r} != {d}" + +def isEqualISMDistanceAttenuation(ref: DISTANCE_ATTENUATION, dut: DISTANCE_ATTENUATION): + assert abs(ref.ref_dist - dut.ref_dist) < 0.0001, "DISTANCE ATTENUATION PI Data mismatch in ref_dist" + assert abs(ref.max_dist - dut.max_dist) < 0.0001, "DISTANCE ATTENUATION PI Data mismatch in max_dist" + assert abs(ref.roll_off - dut.roll_off) < 0.0001, "DISTANCE ATTENUATION PI Data mismatch in roll_off" + +def isEqualISMDirectivity(ref: DIRECTIVITY, dut: DIRECTIVITY): + assert ref.inner_ang == dut.inner_ang, "DIRECTIVITYPI Data mismatch in inner_ang" + assert ref.outer_ang == dut.outer_ang, "DIRECTIVITY PI Data mismatch in outer_ang" + assert abs(ref.outer_att - dut.outer_att) < 0.0001, "DIRECTIVITY PI Data mismatch in outer_att" class CSVREADER: def __init__(self, csvFile: Path): @@ -670,10 +705,27 @@ def run_rtp_bitstream_tests( elif type(generatedPIData[ts][pitype]) == AUDIO_FOCUS: isEqualAudioFocus(AUDIO_FOCUS(**decoded), data) elif type(generatedPIData[ts][pitype]) == list: - for r, d in zip( - generatedPIData[ts][pitype], decodedPiData[ts][pitype] - ): - isEqualAD(AUDIO_DESCRIPTION(**d), r) + if pitype == "AUDIO_DESCRIPTION": + for r, d in zip(generatedPIData[ts][pitype], decodedPiData[ts][pitype]): + isEqualAD(AUDIO_DESCRIPTION(**d), r) + elif pitype == "ISM_ORIENTATION": + for r, d in zip(generatedPIData[ts][pitype], decodedPiData[ts][pitype]): + isEqualOrientation(ORIENTATION(**d), r) + elif pitype == "ISM_POSITION": + for r, d in zip(generatedPIData[ts][pitype], decodedPiData[ts][pitype]): + isEqualPosition(POSITION(**d), r) + elif pitype == "ISM_DISTANCE_ATTENUATION": + for r, d in zip(generatedPIData[ts][pitype], decodedPiData[ts][pitype]): + isEqualISMDistanceAttenuation(DISTANCE_ATTENUATION(**d), r) + elif pitype == "ISM_DIRECTIVITY": + for r, d in zip(generatedPIData[ts][pitype], decodedPiData[ts][pitype]): + isEqualISMDirectivity(DIRECTIVITY(**d), r) + elif type(generatedPIData[ts][pitype]) == ISM_NUM: + isEqualISMNum(ISM_NUM(**decoded), data) + elif type(generatedPIData[ts][pitype]) == ISM_ID: + isEqualISMID(ISM_ID(**decoded), data) + elif type(generatedPIData[ts][pitype]) == ISM_GAIN: + isEqualISMGain(ISM_GAIN(**decoded), data) else: assert False, "Unsupported PI data found"