Loading apps/decoder.c +59 −0 Original line number Diff line number Diff line Loading @@ -123,6 +123,12 @@ typedef struct #endif #endif #ifdef MASAISM_EDIT_OBJECTS bool editing_ism_enabled; int16_t index_of_edited_ism; int16_t azimuth_edited_ism; int16_t elevation_edited_ism; #endif } DecArguments; Loading Loading @@ -496,6 +502,17 @@ int main( } } #ifdef MASAISM_EDIT_OBJECTS /*------------------------------------------------------------------------------------------* * Set edited object positions *------------------------------------------------------------------------------------------*/ if ( arg.editing_ism_enabled ) { IVAS_DEC_SetEditedIsmPositions( hIvasDec, arg.index_of_edited_ism, arg.azimuth_edited_ism, arg.elevation_edited_ism ); } #endif /*-----------------------------------------------------------------* * Decoding *-----------------------------------------------------------------*/ Loading Loading @@ -690,6 +707,9 @@ static bool parseCmdlIVAS_dec( { int16_t i; char argv_to_upper[FILENAME_MAX]; #ifdef MASAISM_EDIT_OBJECTS int32_t tmp; #endif #ifdef DEBUGGING float ftmp; char stmp[FILENAME_MAX]; Loading Loading @@ -731,6 +751,13 @@ static bool parseCmdlIVAS_dec( arg->inputFormat = IVAS_DEC_INPUT_FORMAT_G192; arg->no_diegetic_pan = 0.f; #ifdef MASAISM_EDIT_OBJECTS arg->editing_ism_enabled = false; arg->index_of_edited_ism = 0; arg->azimuth_edited_ism = 0; arg->elevation_edited_ism = 0; #endif /*-----------------------------------------------------------------* * Initialization *-----------------------------------------------------------------*/ Loading Loading @@ -958,6 +985,38 @@ static bool parseCmdlIVAS_dec( } i++; } #ifdef MASAISM_EDIT_OBJECTS else if ( strcmp( argv_to_upper, "-EDIT_ISM" ) == 0 ) /* Edit ISM position: objectID, azimuth (deg), elevation (deg) */ { arg->editing_ism_enabled = true; i++; if ( argc - i <= 6 || argv[i][0] == '-' ) { fprintf( stderr, "Error: Edited ISM position parameters not defined! \n\n" ); usage_dec(); return false; } if ( sscanf( argv[i], "%d", &tmp ) > 0 ) { arg->index_of_edited_ism = tmp; i++; } if ( sscanf( argv[i], "%d", &tmp ) > 0 ) { arg->azimuth_edited_ism = tmp; i++; } if ( sscanf( argv[i], "%d", &tmp ) > 0 ) { arg->elevation_edited_ism = tmp; i++; } } #endif /*-----------------------------------------------------------------* * Option not recognized Loading apps/encoder.c +127 −0 Original line number Diff line number Diff line Loading @@ -98,6 +98,14 @@ typedef union _EncInputFormatConfig /* MC details */ IVAS_ENC_MC_LAYOUT mcLayout; #ifdef MASA_AND_OBJECTS struct EncMasaIsmConfig { int16_t numObjects; const char *metadataFiles[IVAS_MAX_NUM_OBJECTS]; IVAS_ENC_MASA_VARIANT masaVariant; } masa_ism; #endif } EncInputFormatConfig; /* Struct for storing cmdln arguments */ Loading Loading @@ -488,6 +496,15 @@ int main( goto cleanup; } break; #ifdef MASA_AND_OBJECTS case IVAS_ENC_INPUT_MASA_ISM: if ( ( error = IVAS_ENC_ConfigureForMASAObjects( hIvasEnc, arg.inputFs, totalBitrate, bandwidth, arg.dtxConfig, arg.inputFormatConfig.masa_ism.numObjects, arg.inputFormatConfig.masa_ism.masaVariant ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nIVAS_ENC_ConfigureForMASAObjects failed: %s\n\n", IVAS_ENC_GetErrorMessage( error ) ); exit( -1 ); } break; #endif default: fprintf( stderr, "\nInvalid input type\n\n" ); goto cleanup; Loading @@ -513,7 +530,12 @@ int main( } } #ifdef MASA_AND_OBJECTS const int16_t numIsmInputs = ( arg.inputFormat == IVAS_ENC_INPUT_ISM || arg.inputFormat == IVAS_ENC_INPUT_MASA_ISM ) ? arg.inputFormatConfig.ism.numObjects : 0; #else const int16_t numIsmInputs = arg.inputFormat == IVAS_ENC_INPUT_ISM ? arg.inputFormatConfig.ism.numObjects : 0; #endif for ( i = 0; i < numIsmInputs; ++i ) { Loading Loading @@ -1446,6 +1468,100 @@ static bool parseCmdlIVAS_enc( return false; } } #ifdef MASA_AND_OBJECTS else if ( strcmp( to_upper( argv[i] ), "-ISM_MASA" ) == 0 ) { arg->inputFormat = IVAS_ENC_INPUT_MASA_ISM; i++; if ( i < argc - 5 ) { if ( sscanf( argv[i], "%d", &tmp ) > 0 ) { i++; } if ( tmp <= 0 ) { fprintf( stderr, "Error: Too low number of ISM channels specified!\n\n" ); usage_enc(); } else { if ( tmp <= IVAS_MAX_NUM_OBJECTS ) /* number of ISM channels */ { arg->inputFormatConfig.masa_ism.numObjects = (int16_t) tmp; } else { fprintf( stderr, "Error: Too high number of ISM channels!\n\n" ); usage_enc(); } } } else { fprintf( stderr, "Error: Number of ISM channels not specified!\n\n" ); usage_enc(); } if ( i < argc - 4 ) { if ( sscanf( argv[i], "%d", &tmp ) > 0 ) { i++; } switch ( tmp ) { case 1: arg->inputFormatConfig.masa_ism.masaVariant = IVAS_ENC_MASA_1CH; break; case 2: arg->inputFormatConfig.masa_ism.masaVariant = IVAS_ENC_MASA_2CH; break; default: fprintf( stderr, "Error: MASA channels must for the moment be 1 or 2.\n\n" ); usage_enc(); break; } } /* read input metadata files */ for ( j = 0; j < arg->inputFormatConfig.masa_ism.numObjects; j++ ) { if ( i < argc - 4 ) { if ( strcmp( argv[i], "NULL" ) == 0 || strcmp( argv[i], "null" ) == 0 ) { /* no metadata input file -> encode only audio streams */ arg->inputFormatConfig.masa_ism.metadataFiles[j] = NULL; } else { arg->inputFormatConfig.masa_ism.metadataFiles[j] = argv[i]; } i++; } else { fprintf( stderr, "Error: not enough arguments\n\n" ); usage_enc(); } } if ( i < argc - 4 ) { arg->masaMetadataFile = argv[i]; i++; } else { fprintf( stderr, "Error: not enough MASA arguments\n\n" ); usage_enc(); } } #endif else if ( strcmp( argv_to_upper, "-STEREO_DMX_EVS" ) == 0 ) { arg->inputFormat = IVAS_ENC_INPUT_MONO; Loading Loading @@ -1621,6 +1737,10 @@ static void usage_enc( void ) fprintf( stdout, " 96000, 128000, 160000, 192000, 256000) \n" ); fprintf( stdout, " for IVAS SBA, MASA, MC R=(13200, 16400, 24400, 32000, 48000, 64000, 80000, \n" ); fprintf( stdout, " 96000, 128000, 160000, 192000, 256000, 384000, 512000) \n" ); #ifdef MASA_AND_OBJECTS fprintf( stdout, " for IVAS MASA and objects R = (13200, 16400, 24400, 32000, 48000, 64000, 96000, 128000, \n" ); fprintf( stdout, " 160000, 192000, 256000, 384000, 512000)\n" ); #endif fprintf( stdout, " Alternatively, R can be a bitrate switching file which consists of R values\n" ); fprintf( stdout, " indicating the bitrate for each frame in bps. These values are stored in\n" ); fprintf( stdout, " binary format using 4 bytes per value\n" ); Loading @@ -1644,6 +1764,13 @@ static void usage_enc( void ) fprintf( stdout, "-masa Ch File : MASA format \n" ); fprintf( stdout, " where Ch specifies the number of input/transport channels (1 or 2): \n" ); fprintf( stdout, " and File specifies input file containing parametric metadata \n" ); #ifdef MASA_AND_OBJECTS fprintf( stdout, "-ism_masa IsmChannels MasaChannels IsmFiles MasaFile : MASA and objects format \n" ); fprintf( stdout, " where IsmChannels specifies the number of ISms (1-4)\n" ); fprintf( stdout, " and MasaChannels specifies the number of MASA input/transport channels (1 or 2) \n" ); fprintf( stdout, " and IsmFiles specify input files containing metadata, one file per object \n" ); fprintf( stdout, " and MasaFile specifies MASA input file containing parametric metadata \n" ); #endif fprintf( stdout, "-mc InputConf : Multi-channel format\n" ); fprintf( stdout, " where InputConf specifies the channel configuration: 5_1, 7_1, 5_1_2, 5_1_4, 7_1_4\n" ); fprintf( stdout, " Loudspeaker positions are assumed to have azimuth and elevation as per \n" ); Loading lib_com/ivas_cnst.h +22 −1 Original line number Diff line number Diff line Loading @@ -70,7 +70,9 @@ typedef enum SBA_FORMAT, /* IVAS SBA (ambisonics) format */ MASA_FORMAT, /* IVAS MASA format */ MC_FORMAT, /* IVAS multi-channel format */ #ifdef MASA_AND_OBJECTS MASA_ISM_FORMAT, /* IVAS combined MASA + objects format*/ #endif } IVAS_FORMAT; Loading Loading @@ -179,7 +181,11 @@ typedef enum #define MAX_CPE ( MAX_TRANSPORT_CHANNELS / CPE_CHANNELS ) /* max. number of CPEs */ #define MAX_BITS_METADATA 2640 /* max. bit-budget of metadata, one channel */ /* IVAS_fmToDo: to be confirmed for final value once mature */ #ifdef MASA_AND_OBJECTS #define MAX_NUM_METADATA max( 2, MAX_NUM_OBJECTS + 2 ) /* number of max. metadata (now only 2 for DirAC) */ #else #define MAX_NUM_METADATA max( 2, MAX_NUM_OBJECTS ) /* number of max. metadata (now only 2 for DirAC) */ #endif #define IVAS_ENC_DELAY_NS ACELP_LOOK_NS Loading Loading @@ -345,6 +351,12 @@ typedef enum ISM_MODE_NONE, ISM_MODE_DISC, /* discrete ISM */ ISM_MODE_PARAM /* parametric ISM */ #ifdef MASA_AND_OBJECTS , ISM_MASA_MODE_PARAM, /* parametric ISM mode for combined MASA ISM format */ ISM_MASA_MODE_ONE_OBJ, /* MASA ISM mode when one object is encoded separarately */ ISM_MASA_MODE_DISC #endif } ISM_MODE; Loading Loading @@ -1088,6 +1100,12 @@ enum #define MASA_DELTA_AZI_DCT 10 #define MASA_TRANSP_BITS 1 #ifdef MASA_AND_OBJECTS #define MASA_ISM_FORMAT_BITS 1 #define NO_BITS_MASA_ISM_NO_OBJ 2 #define MASA2TOTAL_THR 0.98f #define BITS_MASA2TOTTAL_DCT0 6 #endif #define MASA_HEADER_BITS 2 #define MASA_SUBFRAME_BITS 1 #define MASA_LOWBITRATE_MODE_BITS 1 Loading Loading @@ -1143,6 +1161,9 @@ enum #define MASA_ANGLE_AT_EQUATOR_DEG 0.738796268264740f #define MASA_INV_ANGLE_AT_EQUATOR_DEG 1.353553128183453f #define MASA_STEREO_MIN_BITRATE IVAS_24k4 #ifdef MASA_AND_OBJECTS #define MAXIMUM_OMASA_FREQ_BANDS 8 /* Corresponds to maximum number of coding bands at 32 kbps */ #endif #define MASA_BIT_REDUCT_PARAM 10 #define MASA_MAXIMUM_TWO_DIR_BANDS 18 Loading lib_com/ivas_ism_config.c +100 −2 Original line number Diff line number Diff line Loading @@ -96,6 +96,10 @@ ivas_error ivas_ism_config( int32_t element_brate[], /* o : element bitrate per object */ int32_t total_brate[], /* o : total bitrate per object */ int16_t nb_bits_metadata[] /* i/o: number of metadata bits */ #ifdef MASA_AND_OBJECTS , int16_t masa_ism_flag /* i : flag indicating ISM MASA format */ #endif ) { int16_t ch; Loading @@ -107,9 +111,20 @@ ivas_error ivas_ism_config( int16_t n_ISms; ivas_error error; error = IVAS_ERR_OK; error = IVAS_ERR_OK; #ifdef MASA_AND_OBJECTS if ( masa_ism_flag == 1 ) { n_ISms = num_obj; } else { #endif n_ISms = nchan_transport; #ifdef MASA_AND_OBJECTS } #endif /* initialization */ ism_metadata_flag_global = 0; Loading @@ -131,7 +146,16 @@ ivas_error ivas_ism_config( /* count ISm common signaling bits */ if ( hIsmMeta != NULL ) { #ifdef MASA_AND_OBJECTS nb_bits_metadata[0] += n_ISms * ISM_METADATA_FLAG_BITS; if ( masa_ism_flag == 0 ) { /* the bits for writing the number of objects are counted here for pure ISM modes */ nb_bits_metadata[0] += num_obj; } #else nb_bits_metadata[0] += n_ISms * ISM_METADATA_FLAG_BITS + num_obj; #endif for ( ch = 0; ch < n_ISms; ch++ ) { Loading Loading @@ -490,3 +514,77 @@ ISM_MODE ivas_ism_mode_select( return ism_mode; } #ifdef MASA_AND_OBJECTS /*--------------------------------------------------------------- * ivas_omasa_ism_mode_select() * * selects the ISM mode base on bit-rate and number of objects in the combined ISM MASA format mode * ---------------------------------------------------------------*/ /*! r : ISM format mode */ ISM_MODE ivas_omasa_ism_mode_select( const int32_t ivas_total_brate, /* i : IVAS total bitrate */ const int16_t no_obj /* i : number of objects */ ) { ISM_MODE ism_mode = ISM_MODE_NONE; switch ( no_obj ) { case 1: if ( ivas_total_brate >= IVAS_64k ) { ism_mode = ISM_MASA_MODE_DISC; } else if ( ivas_total_brate >= IVAS_48k ) { ism_mode = ISM_MASA_MODE_PARAM; } else { ism_mode = ISM_MODE_NONE; } break; case 2: if ( ivas_total_brate >= IVAS_80k ) { ism_mode = ISM_MASA_MODE_DISC; } else if ( ivas_total_brate >= IVAS_64k ) { ism_mode = ISM_MASA_MODE_ONE_OBJ; } else if ( ivas_total_brate >= IVAS_48k ) { ism_mode = ISM_MASA_MODE_PARAM; } else { ism_mode = ISM_MODE_NONE; } break; case 3: case 4: if ( ivas_total_brate >= IVAS_160k ) { ism_mode = ISM_MASA_MODE_DISC; } else if ( ivas_total_brate >= IVAS_80k ) { ism_mode = ISM_MASA_MODE_ONE_OBJ; } else if ( ivas_total_brate >= IVAS_48k ) { ism_mode = ISM_MASA_MODE_PARAM; } else { ism_mode = ISM_MODE_NONE; } break; } return ism_mode; } #endif lib_com/ivas_masa_com.c +248 −1 Original line number Diff line number Diff line Loading @@ -66,6 +66,12 @@ void ivas_masa_set_elements( int16_t *element_mode, /* o : element mode */ int16_t *nSCE, /* o : number of SCEs */ int16_t *nCPE /* o : number of CPEs */ #ifdef MASA_AND_OBJECTS , int16_t ivas_format, const ISM_MODE ism_mode, int32_t sce_brate #endif ) { if ( nchan_transport == 2 ) Loading @@ -78,16 +84,43 @@ void ivas_masa_set_elements( *element_mode = IVAS_SCE; /* This is needed for the initialization phase to initialize codec mode to SCE, since it is written first to the file*/ } else #ifdef MASA_AND_OBJECTS if ( ivas_format == MASA_ISM_FORMAT && ism_mode != ISM_MODE_NONE ) { *nCPE = 1; if ( *element_mode == -1 ) { *element_mode = IVAS_CPE_DFT; /* To have it initialized in case it was not already. */ } if ( ivas_total_brate > MIN_BRATE_MDCT_STEREO ) { *element_mode = IVAS_CPE_MDCT; if ( ( ism_mode == ISM_MASA_MODE_DISC || ism_mode == ISM_MASA_MODE_ONE_OBJ ) && ( ivas_total_brate - sce_brate < MIN_BRATE_MDCT_STEREO ) ) { *element_mode = IVAS_CPE_DFT; } } } else #endif { *nCPE = 1; *nSCE = 0; if ( ivas_total_brate > IVAS_48k ) if ( ivas_total_brate > MIN_BRATE_MDCT_STEREO ) { *element_mode = IVAS_CPE_MDCT; } } hQMetaData->bits_frame_nominal = (int16_t) ( ivas_total_brate / FRAMES_PER_SEC ); #ifdef MASA_AND_OBJECTS if ( ivas_format == MASA_ISM_FORMAT && ( ism_mode == ISM_MASA_MODE_ONE_OBJ || ism_mode == ISM_MASA_MODE_DISC ) ) { hQMetaData->bits_frame_nominal -= (int16_t) ( sce_brate / FRAMES_PER_SEC ); } #endif } else if ( nchan_transport == 1 ) { Loading Loading @@ -388,3 +421,217 @@ void masa_sample_rate_band_correction( return; } #ifdef MASA_AND_OBJECTS /*--------------------------------------------------------------- * valid() * * Checking validity of the index of an ISM ratio index vector, * within the indexing function. *---------------------------------------------------------------*/ int16_t valid( /* o: valid or not 1/0 */ int16_t index, /* i: index to be checked */ int16_t K, /* i: L1 norm to check against */ int16_t len /* i: vector length */ ) { int16_t out; int16_t i, sum, elem; int16_t base[4]; sum = 0; set_s( base, 1, len ); for ( i = 1; i < len; i++ ) { base[i] = base[i - 1] * 10; } sum = 0; for ( i = len - 1; i >= 0; i-- ) { elem = index / base[i]; sum += elem; index -= elem * base[i]; } if ( sum <= K ) { out = 1; } else { out = 0; } return out; } /*--------------------------------------------------------------- * reconstruct_ism_ratios() * * Obtains ISM ratio values from the quantized indexes *---------------------------------------------------------------*/ void reconstruct_ism_ratios( int16_t *ratio_ism_idx, /* i: index vector */ int16_t n_ism, /* i: number of components/objects */ float step, /* i: quantization step */ float *q_energy_ratio_ism /* o: reconstructed ISM values */ ) { int16_t i; float sum; sum = 0; for ( i = 0; i < n_ism - 1; i++ ) { q_energy_ratio_ism[i] = ratio_ism_idx[i] * step; sum += q_energy_ratio_ism[i]; } q_energy_ratio_ism[n_ism - 1] = 1.0f - sum; return; } /*--------------------------------------------------------------- * modify_masa_energy_ratios() * * Updates energy ratios by taking into account the MASA content contribution * to the total audio scene *---------------------------------------------------------------*/ void modify_masa_energy_ratios( IVAS_QMETADATA_HANDLE hQMetaData /* i/o: Metadata handle */ ) { int16_t i, m, d, b; for ( m = 0; m < MAX_PARAM_SPATIAL_SUBFRAMES; m++ ) { if ( hQMetaData->q_direction[0].cfg.nblocks == 1 ) { i = 0; } else { i = m; } for ( b = 0; b < hQMetaData->q_direction[0].cfg.nbands; b++ ) { for ( d = 0; d < hQMetaData->no_directions; d++ ) { hQMetaData->q_direction[d].band_data[b].energy_ratio[m] = hQMetaData->q_direction[d].band_data[b].energy_ratio[m] * hQMetaData->masa_to_total_energy_ratio[i][b]; } } } } /*--------------------------------------------------------------- * ivas_get_stereo_panning_gains() * * *---------------------------------------------------------------*/ void ivas_get_stereo_panning_gains( float aziDeg, float eleDeg, float panningGains[2] ) { float aziRad, eleRad; float y, mappedX, aziRadMapped, A, A2, A3; const float LsAngleRad = 30.0f * PI_OVER_180; /* Convert azi and ele to an azi value of the cone of confusion */ aziRad = aziDeg * PI_OVER_180; eleRad = eleDeg * PI_OVER_180; y = ( sinf( aziRad ) * cosf( eleRad ) ); mappedX = sqrtf( max( 0.0f, 1.0f - ( y * y ) ) ); aziRadMapped = atan2f( y, mappedX ); if ( aziRadMapped >= LsAngleRad ) { /* Left side */ panningGains[0] = 1.0f; panningGains[1] = 0.0f; } else if ( aziRadMapped <= -LsAngleRad ) { /* Right side */ panningGains[0] = 0.0f; panningGains[1] = 1.0f; } else /* Tangent panning law */ { A = tanf( aziRadMapped ) / tanf( LsAngleRad ); A2 = ( A - 1.0f ) / max( 0.001f, A + 1.0f ); A3 = 1.0f / ( A2 * A2 + 1.0f ); panningGains[0] = sqrtf( A3 ); panningGains[1] = sqrtf( 1.0f - A3 ); } } /*--------------------------------------------------------------- * distribute_evenly_ism() * * Obtain ISM ratio indexes for even content distribution bbetween objects *---------------------------------------------------------------*/ void distribute_evenly_ism( int16_t *idx, /* o: index values */ int16_t K, /* i: sum of indexes */ int16_t no_ism /* i: number of objects */ ) { int16_t i; int16_t sum; sum = 0; for ( i = 0; i < no_ism; i++ ) { idx[i] = (int16_t) ( K / no_ism ); sum += idx[i]; } assert( sum <= K ); i = 0; while ( sum < K ) { if ( i == no_ism ) { i = 0; } idx[i]++; sum++; i++; } } /*--------------------------------------------------------------- * calculate_cpe_brate_MASA_ISM() * * Calculates bitrate for MASA_ISM mode that is not used for separated objects, * * but for the CPE part (metadata included) *---------------------------------------------------------------*/ int32_t /* o: cpe bitrate value */ calculate_cpe_brate_MASA_ISM( ISM_MODE ism_mode, /* i: ism mode */ int32_t ivas_total_brate, /* i: total bit rate for IVAS */ int16_t n_ism ) /* i: number of objects */ { int32_t cpe_brate; int16_t k, sce_id; k = 0; while ( k < SIZE_IVAS_BRATE_TBL && ivas_total_brate != ivas_brate_tbl[k] ) { k++; } if ( ism_mode == ISM_MASA_MODE_ONE_OBJ ) { cpe_brate = ivas_total_brate - sep_object_brate[k - 2][0]; /* take data from the first column */ } else if ( ism_mode == ISM_MASA_MODE_DISC ) { cpe_brate = ivas_total_brate; for ( sce_id = 0; sce_id < n_ism; sce_id++ ) { cpe_brate -= sep_object_brate[k - 2][n_ism - 1]; } } else { cpe_brate = ivas_total_brate; } return cpe_brate; } #endif Loading
apps/decoder.c +59 −0 Original line number Diff line number Diff line Loading @@ -123,6 +123,12 @@ typedef struct #endif #endif #ifdef MASAISM_EDIT_OBJECTS bool editing_ism_enabled; int16_t index_of_edited_ism; int16_t azimuth_edited_ism; int16_t elevation_edited_ism; #endif } DecArguments; Loading Loading @@ -496,6 +502,17 @@ int main( } } #ifdef MASAISM_EDIT_OBJECTS /*------------------------------------------------------------------------------------------* * Set edited object positions *------------------------------------------------------------------------------------------*/ if ( arg.editing_ism_enabled ) { IVAS_DEC_SetEditedIsmPositions( hIvasDec, arg.index_of_edited_ism, arg.azimuth_edited_ism, arg.elevation_edited_ism ); } #endif /*-----------------------------------------------------------------* * Decoding *-----------------------------------------------------------------*/ Loading Loading @@ -690,6 +707,9 @@ static bool parseCmdlIVAS_dec( { int16_t i; char argv_to_upper[FILENAME_MAX]; #ifdef MASAISM_EDIT_OBJECTS int32_t tmp; #endif #ifdef DEBUGGING float ftmp; char stmp[FILENAME_MAX]; Loading Loading @@ -731,6 +751,13 @@ static bool parseCmdlIVAS_dec( arg->inputFormat = IVAS_DEC_INPUT_FORMAT_G192; arg->no_diegetic_pan = 0.f; #ifdef MASAISM_EDIT_OBJECTS arg->editing_ism_enabled = false; arg->index_of_edited_ism = 0; arg->azimuth_edited_ism = 0; arg->elevation_edited_ism = 0; #endif /*-----------------------------------------------------------------* * Initialization *-----------------------------------------------------------------*/ Loading Loading @@ -958,6 +985,38 @@ static bool parseCmdlIVAS_dec( } i++; } #ifdef MASAISM_EDIT_OBJECTS else if ( strcmp( argv_to_upper, "-EDIT_ISM" ) == 0 ) /* Edit ISM position: objectID, azimuth (deg), elevation (deg) */ { arg->editing_ism_enabled = true; i++; if ( argc - i <= 6 || argv[i][0] == '-' ) { fprintf( stderr, "Error: Edited ISM position parameters not defined! \n\n" ); usage_dec(); return false; } if ( sscanf( argv[i], "%d", &tmp ) > 0 ) { arg->index_of_edited_ism = tmp; i++; } if ( sscanf( argv[i], "%d", &tmp ) > 0 ) { arg->azimuth_edited_ism = tmp; i++; } if ( sscanf( argv[i], "%d", &tmp ) > 0 ) { arg->elevation_edited_ism = tmp; i++; } } #endif /*-----------------------------------------------------------------* * Option not recognized Loading
apps/encoder.c +127 −0 Original line number Diff line number Diff line Loading @@ -98,6 +98,14 @@ typedef union _EncInputFormatConfig /* MC details */ IVAS_ENC_MC_LAYOUT mcLayout; #ifdef MASA_AND_OBJECTS struct EncMasaIsmConfig { int16_t numObjects; const char *metadataFiles[IVAS_MAX_NUM_OBJECTS]; IVAS_ENC_MASA_VARIANT masaVariant; } masa_ism; #endif } EncInputFormatConfig; /* Struct for storing cmdln arguments */ Loading Loading @@ -488,6 +496,15 @@ int main( goto cleanup; } break; #ifdef MASA_AND_OBJECTS case IVAS_ENC_INPUT_MASA_ISM: if ( ( error = IVAS_ENC_ConfigureForMASAObjects( hIvasEnc, arg.inputFs, totalBitrate, bandwidth, arg.dtxConfig, arg.inputFormatConfig.masa_ism.numObjects, arg.inputFormatConfig.masa_ism.masaVariant ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nIVAS_ENC_ConfigureForMASAObjects failed: %s\n\n", IVAS_ENC_GetErrorMessage( error ) ); exit( -1 ); } break; #endif default: fprintf( stderr, "\nInvalid input type\n\n" ); goto cleanup; Loading @@ -513,7 +530,12 @@ int main( } } #ifdef MASA_AND_OBJECTS const int16_t numIsmInputs = ( arg.inputFormat == IVAS_ENC_INPUT_ISM || arg.inputFormat == IVAS_ENC_INPUT_MASA_ISM ) ? arg.inputFormatConfig.ism.numObjects : 0; #else const int16_t numIsmInputs = arg.inputFormat == IVAS_ENC_INPUT_ISM ? arg.inputFormatConfig.ism.numObjects : 0; #endif for ( i = 0; i < numIsmInputs; ++i ) { Loading Loading @@ -1446,6 +1468,100 @@ static bool parseCmdlIVAS_enc( return false; } } #ifdef MASA_AND_OBJECTS else if ( strcmp( to_upper( argv[i] ), "-ISM_MASA" ) == 0 ) { arg->inputFormat = IVAS_ENC_INPUT_MASA_ISM; i++; if ( i < argc - 5 ) { if ( sscanf( argv[i], "%d", &tmp ) > 0 ) { i++; } if ( tmp <= 0 ) { fprintf( stderr, "Error: Too low number of ISM channels specified!\n\n" ); usage_enc(); } else { if ( tmp <= IVAS_MAX_NUM_OBJECTS ) /* number of ISM channels */ { arg->inputFormatConfig.masa_ism.numObjects = (int16_t) tmp; } else { fprintf( stderr, "Error: Too high number of ISM channels!\n\n" ); usage_enc(); } } } else { fprintf( stderr, "Error: Number of ISM channels not specified!\n\n" ); usage_enc(); } if ( i < argc - 4 ) { if ( sscanf( argv[i], "%d", &tmp ) > 0 ) { i++; } switch ( tmp ) { case 1: arg->inputFormatConfig.masa_ism.masaVariant = IVAS_ENC_MASA_1CH; break; case 2: arg->inputFormatConfig.masa_ism.masaVariant = IVAS_ENC_MASA_2CH; break; default: fprintf( stderr, "Error: MASA channels must for the moment be 1 or 2.\n\n" ); usage_enc(); break; } } /* read input metadata files */ for ( j = 0; j < arg->inputFormatConfig.masa_ism.numObjects; j++ ) { if ( i < argc - 4 ) { if ( strcmp( argv[i], "NULL" ) == 0 || strcmp( argv[i], "null" ) == 0 ) { /* no metadata input file -> encode only audio streams */ arg->inputFormatConfig.masa_ism.metadataFiles[j] = NULL; } else { arg->inputFormatConfig.masa_ism.metadataFiles[j] = argv[i]; } i++; } else { fprintf( stderr, "Error: not enough arguments\n\n" ); usage_enc(); } } if ( i < argc - 4 ) { arg->masaMetadataFile = argv[i]; i++; } else { fprintf( stderr, "Error: not enough MASA arguments\n\n" ); usage_enc(); } } #endif else if ( strcmp( argv_to_upper, "-STEREO_DMX_EVS" ) == 0 ) { arg->inputFormat = IVAS_ENC_INPUT_MONO; Loading Loading @@ -1621,6 +1737,10 @@ static void usage_enc( void ) fprintf( stdout, " 96000, 128000, 160000, 192000, 256000) \n" ); fprintf( stdout, " for IVAS SBA, MASA, MC R=(13200, 16400, 24400, 32000, 48000, 64000, 80000, \n" ); fprintf( stdout, " 96000, 128000, 160000, 192000, 256000, 384000, 512000) \n" ); #ifdef MASA_AND_OBJECTS fprintf( stdout, " for IVAS MASA and objects R = (13200, 16400, 24400, 32000, 48000, 64000, 96000, 128000, \n" ); fprintf( stdout, " 160000, 192000, 256000, 384000, 512000)\n" ); #endif fprintf( stdout, " Alternatively, R can be a bitrate switching file which consists of R values\n" ); fprintf( stdout, " indicating the bitrate for each frame in bps. These values are stored in\n" ); fprintf( stdout, " binary format using 4 bytes per value\n" ); Loading @@ -1644,6 +1764,13 @@ static void usage_enc( void ) fprintf( stdout, "-masa Ch File : MASA format \n" ); fprintf( stdout, " where Ch specifies the number of input/transport channels (1 or 2): \n" ); fprintf( stdout, " and File specifies input file containing parametric metadata \n" ); #ifdef MASA_AND_OBJECTS fprintf( stdout, "-ism_masa IsmChannels MasaChannels IsmFiles MasaFile : MASA and objects format \n" ); fprintf( stdout, " where IsmChannels specifies the number of ISms (1-4)\n" ); fprintf( stdout, " and MasaChannels specifies the number of MASA input/transport channels (1 or 2) \n" ); fprintf( stdout, " and IsmFiles specify input files containing metadata, one file per object \n" ); fprintf( stdout, " and MasaFile specifies MASA input file containing parametric metadata \n" ); #endif fprintf( stdout, "-mc InputConf : Multi-channel format\n" ); fprintf( stdout, " where InputConf specifies the channel configuration: 5_1, 7_1, 5_1_2, 5_1_4, 7_1_4\n" ); fprintf( stdout, " Loudspeaker positions are assumed to have azimuth and elevation as per \n" ); Loading
lib_com/ivas_cnst.h +22 −1 Original line number Diff line number Diff line Loading @@ -70,7 +70,9 @@ typedef enum SBA_FORMAT, /* IVAS SBA (ambisonics) format */ MASA_FORMAT, /* IVAS MASA format */ MC_FORMAT, /* IVAS multi-channel format */ #ifdef MASA_AND_OBJECTS MASA_ISM_FORMAT, /* IVAS combined MASA + objects format*/ #endif } IVAS_FORMAT; Loading Loading @@ -179,7 +181,11 @@ typedef enum #define MAX_CPE ( MAX_TRANSPORT_CHANNELS / CPE_CHANNELS ) /* max. number of CPEs */ #define MAX_BITS_METADATA 2640 /* max. bit-budget of metadata, one channel */ /* IVAS_fmToDo: to be confirmed for final value once mature */ #ifdef MASA_AND_OBJECTS #define MAX_NUM_METADATA max( 2, MAX_NUM_OBJECTS + 2 ) /* number of max. metadata (now only 2 for DirAC) */ #else #define MAX_NUM_METADATA max( 2, MAX_NUM_OBJECTS ) /* number of max. metadata (now only 2 for DirAC) */ #endif #define IVAS_ENC_DELAY_NS ACELP_LOOK_NS Loading Loading @@ -345,6 +351,12 @@ typedef enum ISM_MODE_NONE, ISM_MODE_DISC, /* discrete ISM */ ISM_MODE_PARAM /* parametric ISM */ #ifdef MASA_AND_OBJECTS , ISM_MASA_MODE_PARAM, /* parametric ISM mode for combined MASA ISM format */ ISM_MASA_MODE_ONE_OBJ, /* MASA ISM mode when one object is encoded separarately */ ISM_MASA_MODE_DISC #endif } ISM_MODE; Loading Loading @@ -1088,6 +1100,12 @@ enum #define MASA_DELTA_AZI_DCT 10 #define MASA_TRANSP_BITS 1 #ifdef MASA_AND_OBJECTS #define MASA_ISM_FORMAT_BITS 1 #define NO_BITS_MASA_ISM_NO_OBJ 2 #define MASA2TOTAL_THR 0.98f #define BITS_MASA2TOTTAL_DCT0 6 #endif #define MASA_HEADER_BITS 2 #define MASA_SUBFRAME_BITS 1 #define MASA_LOWBITRATE_MODE_BITS 1 Loading Loading @@ -1143,6 +1161,9 @@ enum #define MASA_ANGLE_AT_EQUATOR_DEG 0.738796268264740f #define MASA_INV_ANGLE_AT_EQUATOR_DEG 1.353553128183453f #define MASA_STEREO_MIN_BITRATE IVAS_24k4 #ifdef MASA_AND_OBJECTS #define MAXIMUM_OMASA_FREQ_BANDS 8 /* Corresponds to maximum number of coding bands at 32 kbps */ #endif #define MASA_BIT_REDUCT_PARAM 10 #define MASA_MAXIMUM_TWO_DIR_BANDS 18 Loading
lib_com/ivas_ism_config.c +100 −2 Original line number Diff line number Diff line Loading @@ -96,6 +96,10 @@ ivas_error ivas_ism_config( int32_t element_brate[], /* o : element bitrate per object */ int32_t total_brate[], /* o : total bitrate per object */ int16_t nb_bits_metadata[] /* i/o: number of metadata bits */ #ifdef MASA_AND_OBJECTS , int16_t masa_ism_flag /* i : flag indicating ISM MASA format */ #endif ) { int16_t ch; Loading @@ -107,9 +111,20 @@ ivas_error ivas_ism_config( int16_t n_ISms; ivas_error error; error = IVAS_ERR_OK; error = IVAS_ERR_OK; #ifdef MASA_AND_OBJECTS if ( masa_ism_flag == 1 ) { n_ISms = num_obj; } else { #endif n_ISms = nchan_transport; #ifdef MASA_AND_OBJECTS } #endif /* initialization */ ism_metadata_flag_global = 0; Loading @@ -131,7 +146,16 @@ ivas_error ivas_ism_config( /* count ISm common signaling bits */ if ( hIsmMeta != NULL ) { #ifdef MASA_AND_OBJECTS nb_bits_metadata[0] += n_ISms * ISM_METADATA_FLAG_BITS; if ( masa_ism_flag == 0 ) { /* the bits for writing the number of objects are counted here for pure ISM modes */ nb_bits_metadata[0] += num_obj; } #else nb_bits_metadata[0] += n_ISms * ISM_METADATA_FLAG_BITS + num_obj; #endif for ( ch = 0; ch < n_ISms; ch++ ) { Loading Loading @@ -490,3 +514,77 @@ ISM_MODE ivas_ism_mode_select( return ism_mode; } #ifdef MASA_AND_OBJECTS /*--------------------------------------------------------------- * ivas_omasa_ism_mode_select() * * selects the ISM mode base on bit-rate and number of objects in the combined ISM MASA format mode * ---------------------------------------------------------------*/ /*! r : ISM format mode */ ISM_MODE ivas_omasa_ism_mode_select( const int32_t ivas_total_brate, /* i : IVAS total bitrate */ const int16_t no_obj /* i : number of objects */ ) { ISM_MODE ism_mode = ISM_MODE_NONE; switch ( no_obj ) { case 1: if ( ivas_total_brate >= IVAS_64k ) { ism_mode = ISM_MASA_MODE_DISC; } else if ( ivas_total_brate >= IVAS_48k ) { ism_mode = ISM_MASA_MODE_PARAM; } else { ism_mode = ISM_MODE_NONE; } break; case 2: if ( ivas_total_brate >= IVAS_80k ) { ism_mode = ISM_MASA_MODE_DISC; } else if ( ivas_total_brate >= IVAS_64k ) { ism_mode = ISM_MASA_MODE_ONE_OBJ; } else if ( ivas_total_brate >= IVAS_48k ) { ism_mode = ISM_MASA_MODE_PARAM; } else { ism_mode = ISM_MODE_NONE; } break; case 3: case 4: if ( ivas_total_brate >= IVAS_160k ) { ism_mode = ISM_MASA_MODE_DISC; } else if ( ivas_total_brate >= IVAS_80k ) { ism_mode = ISM_MASA_MODE_ONE_OBJ; } else if ( ivas_total_brate >= IVAS_48k ) { ism_mode = ISM_MASA_MODE_PARAM; } else { ism_mode = ISM_MODE_NONE; } break; } return ism_mode; } #endif
lib_com/ivas_masa_com.c +248 −1 Original line number Diff line number Diff line Loading @@ -66,6 +66,12 @@ void ivas_masa_set_elements( int16_t *element_mode, /* o : element mode */ int16_t *nSCE, /* o : number of SCEs */ int16_t *nCPE /* o : number of CPEs */ #ifdef MASA_AND_OBJECTS , int16_t ivas_format, const ISM_MODE ism_mode, int32_t sce_brate #endif ) { if ( nchan_transport == 2 ) Loading @@ -78,16 +84,43 @@ void ivas_masa_set_elements( *element_mode = IVAS_SCE; /* This is needed for the initialization phase to initialize codec mode to SCE, since it is written first to the file*/ } else #ifdef MASA_AND_OBJECTS if ( ivas_format == MASA_ISM_FORMAT && ism_mode != ISM_MODE_NONE ) { *nCPE = 1; if ( *element_mode == -1 ) { *element_mode = IVAS_CPE_DFT; /* To have it initialized in case it was not already. */ } if ( ivas_total_brate > MIN_BRATE_MDCT_STEREO ) { *element_mode = IVAS_CPE_MDCT; if ( ( ism_mode == ISM_MASA_MODE_DISC || ism_mode == ISM_MASA_MODE_ONE_OBJ ) && ( ivas_total_brate - sce_brate < MIN_BRATE_MDCT_STEREO ) ) { *element_mode = IVAS_CPE_DFT; } } } else #endif { *nCPE = 1; *nSCE = 0; if ( ivas_total_brate > IVAS_48k ) if ( ivas_total_brate > MIN_BRATE_MDCT_STEREO ) { *element_mode = IVAS_CPE_MDCT; } } hQMetaData->bits_frame_nominal = (int16_t) ( ivas_total_brate / FRAMES_PER_SEC ); #ifdef MASA_AND_OBJECTS if ( ivas_format == MASA_ISM_FORMAT && ( ism_mode == ISM_MASA_MODE_ONE_OBJ || ism_mode == ISM_MASA_MODE_DISC ) ) { hQMetaData->bits_frame_nominal -= (int16_t) ( sce_brate / FRAMES_PER_SEC ); } #endif } else if ( nchan_transport == 1 ) { Loading Loading @@ -388,3 +421,217 @@ void masa_sample_rate_band_correction( return; } #ifdef MASA_AND_OBJECTS /*--------------------------------------------------------------- * valid() * * Checking validity of the index of an ISM ratio index vector, * within the indexing function. *---------------------------------------------------------------*/ int16_t valid( /* o: valid or not 1/0 */ int16_t index, /* i: index to be checked */ int16_t K, /* i: L1 norm to check against */ int16_t len /* i: vector length */ ) { int16_t out; int16_t i, sum, elem; int16_t base[4]; sum = 0; set_s( base, 1, len ); for ( i = 1; i < len; i++ ) { base[i] = base[i - 1] * 10; } sum = 0; for ( i = len - 1; i >= 0; i-- ) { elem = index / base[i]; sum += elem; index -= elem * base[i]; } if ( sum <= K ) { out = 1; } else { out = 0; } return out; } /*--------------------------------------------------------------- * reconstruct_ism_ratios() * * Obtains ISM ratio values from the quantized indexes *---------------------------------------------------------------*/ void reconstruct_ism_ratios( int16_t *ratio_ism_idx, /* i: index vector */ int16_t n_ism, /* i: number of components/objects */ float step, /* i: quantization step */ float *q_energy_ratio_ism /* o: reconstructed ISM values */ ) { int16_t i; float sum; sum = 0; for ( i = 0; i < n_ism - 1; i++ ) { q_energy_ratio_ism[i] = ratio_ism_idx[i] * step; sum += q_energy_ratio_ism[i]; } q_energy_ratio_ism[n_ism - 1] = 1.0f - sum; return; } /*--------------------------------------------------------------- * modify_masa_energy_ratios() * * Updates energy ratios by taking into account the MASA content contribution * to the total audio scene *---------------------------------------------------------------*/ void modify_masa_energy_ratios( IVAS_QMETADATA_HANDLE hQMetaData /* i/o: Metadata handle */ ) { int16_t i, m, d, b; for ( m = 0; m < MAX_PARAM_SPATIAL_SUBFRAMES; m++ ) { if ( hQMetaData->q_direction[0].cfg.nblocks == 1 ) { i = 0; } else { i = m; } for ( b = 0; b < hQMetaData->q_direction[0].cfg.nbands; b++ ) { for ( d = 0; d < hQMetaData->no_directions; d++ ) { hQMetaData->q_direction[d].band_data[b].energy_ratio[m] = hQMetaData->q_direction[d].band_data[b].energy_ratio[m] * hQMetaData->masa_to_total_energy_ratio[i][b]; } } } } /*--------------------------------------------------------------- * ivas_get_stereo_panning_gains() * * *---------------------------------------------------------------*/ void ivas_get_stereo_panning_gains( float aziDeg, float eleDeg, float panningGains[2] ) { float aziRad, eleRad; float y, mappedX, aziRadMapped, A, A2, A3; const float LsAngleRad = 30.0f * PI_OVER_180; /* Convert azi and ele to an azi value of the cone of confusion */ aziRad = aziDeg * PI_OVER_180; eleRad = eleDeg * PI_OVER_180; y = ( sinf( aziRad ) * cosf( eleRad ) ); mappedX = sqrtf( max( 0.0f, 1.0f - ( y * y ) ) ); aziRadMapped = atan2f( y, mappedX ); if ( aziRadMapped >= LsAngleRad ) { /* Left side */ panningGains[0] = 1.0f; panningGains[1] = 0.0f; } else if ( aziRadMapped <= -LsAngleRad ) { /* Right side */ panningGains[0] = 0.0f; panningGains[1] = 1.0f; } else /* Tangent panning law */ { A = tanf( aziRadMapped ) / tanf( LsAngleRad ); A2 = ( A - 1.0f ) / max( 0.001f, A + 1.0f ); A3 = 1.0f / ( A2 * A2 + 1.0f ); panningGains[0] = sqrtf( A3 ); panningGains[1] = sqrtf( 1.0f - A3 ); } } /*--------------------------------------------------------------- * distribute_evenly_ism() * * Obtain ISM ratio indexes for even content distribution bbetween objects *---------------------------------------------------------------*/ void distribute_evenly_ism( int16_t *idx, /* o: index values */ int16_t K, /* i: sum of indexes */ int16_t no_ism /* i: number of objects */ ) { int16_t i; int16_t sum; sum = 0; for ( i = 0; i < no_ism; i++ ) { idx[i] = (int16_t) ( K / no_ism ); sum += idx[i]; } assert( sum <= K ); i = 0; while ( sum < K ) { if ( i == no_ism ) { i = 0; } idx[i]++; sum++; i++; } } /*--------------------------------------------------------------- * calculate_cpe_brate_MASA_ISM() * * Calculates bitrate for MASA_ISM mode that is not used for separated objects, * * but for the CPE part (metadata included) *---------------------------------------------------------------*/ int32_t /* o: cpe bitrate value */ calculate_cpe_brate_MASA_ISM( ISM_MODE ism_mode, /* i: ism mode */ int32_t ivas_total_brate, /* i: total bit rate for IVAS */ int16_t n_ism ) /* i: number of objects */ { int32_t cpe_brate; int16_t k, sce_id; k = 0; while ( k < SIZE_IVAS_BRATE_TBL && ivas_total_brate != ivas_brate_tbl[k] ) { k++; } if ( ism_mode == ISM_MASA_MODE_ONE_OBJ ) { cpe_brate = ivas_total_brate - sep_object_brate[k - 2][0]; /* take data from the first column */ } else if ( ism_mode == ISM_MASA_MODE_DISC ) { cpe_brate = ivas_total_brate; for ( sce_id = 0; sce_id < n_ism; sce_id++ ) { cpe_brate -= sep_object_brate[k - 2][n_ism - 1]; } } else { cpe_brate = ivas_total_brate; } return cpe_brate; } #endif