diff --git a/lib_com/ivas_cnst.h b/lib_com/ivas_cnst.h index 834488f6a775709c1f809ecf770dd96cce18122e..51bbe7995e64dc89ad8c69bcdeb656fee3b2b85f 100644 --- a/lib_com/ivas_cnst.h +++ b/lib_com/ivas_cnst.h @@ -1187,6 +1187,12 @@ enum #define MASA_BIT_REDUCT_PARAM 10 #define MASA_MAXIMUM_TWO_DIR_BANDS 18 + +#ifdef NOKIA_MASA_DESCRIPTIVE_META_TRANSMISSION +#define MASA_DESC_META_LEVEL2_BRATE IVAS_64k +#define MASA_DESC_META_LEVEL3_BRATE IVAS_96k +#endif + typedef enum { MASA_STEREO_NOT_DEFINED, diff --git a/lib_com/ivas_masa_com.c b/lib_com/ivas_masa_com.c index e576c725b21a3d8d9ebc5f6d338fe202ee7b1f30..21fb53abe46c305c29f6ec79a8d3aff60142c27c 100644 --- a/lib_com/ivas_masa_com.c +++ b/lib_com/ivas_masa_com.c @@ -411,3 +411,34 @@ void masa_sample_rate_band_correction( return; } + +#ifdef NOKIA_MASA_DESCRIPTIVE_META_TRANSMISSION +/*--------------------------------------------------------------- + * ivas_masa_map_meta_channel_layout_to_mc_ls_setup() + * + * Maps channel layout metadata from descriptive MASA metadata to + * MC LS SETUP type. + * -------------------------------------------------------------*/ + +/*! r : multi channel loudspeaker setup */ +MC_LS_SETUP ivas_masa_map_meta_channel_layout_to_mc_ls_setup( + const uint8_t channelLayout /* i: Input value from descriptive metadata */ +) +{ + switch ( channelLayout ) + { + case 0x3: + return MC_LS_SETUP_5_1; + case 0x4: + return MC_LS_SETUP_5_1_2; + case 0x5: + return MC_LS_SETUP_5_1_4; + case 0x6: + return MC_LS_SETUP_7_1; + case 0x7: + return MC_LS_SETUP_7_1_4; + } + + return MC_LS_SETUP_INVALID; +} +#endif diff --git a/lib_com/ivas_prot.h b/lib_com/ivas_prot.h index 261b1d38a8113ae3b90389bd90b7b20ee274554f..17f9a008133fc4d3125c4be5f00c242fffc1d582 100755 --- a/lib_com/ivas_prot.h +++ b/lib_com/ivas_prot.h @@ -4562,6 +4562,13 @@ void ivas_masa_set_coding_config( const uint8_t isMcMasa /* i : toggle for selecting McMASA specific config */ ); +#ifdef NOKIA_MASA_DESCRIPTIVE_META_TRANSMISSION +/*! r : multi channel loudspeaker setup */ +MC_LS_SETUP ivas_masa_map_meta_channel_layout_to_mc_ls_setup( + const uint8_t channelLayout /* i : Input value from descriptive metadata */ +); +#endif + /*! r: Surround coherence significant flag */ uint8_t ivas_masa_surrcoh_signicant( float surroundingCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i : Surround coherence */ diff --git a/lib_com/ivas_rom_com.c b/lib_com/ivas_rom_com.c index 6677b53a9f5d3fe543f0f7722cd65a783d8c628b..4f61897a4e72df1ee355238b92a26ef248a05d80 100644 --- a/lib_com/ivas_rom_com.c +++ b/lib_com/ivas_rom_com.c @@ -2701,7 +2701,11 @@ const int16_t MASA_grouping_24_to_5[24] = /* IVAS_13k2, IVAS_16k4, IVAS_24k4, IVAS_32k, IVAS_48k, IVAS_64k, IVAS_80k, IVAS_96k, IVAS_128k, IVAS_160k, IVAS_192k, IVAS_256k, IVAS_384k, IVAS_512k */ const int16_t masa_bits[IVAS_NUM_ACTIVE_BRATES] = { +#ifdef NOKIA_MASA_DESCRIPTIVE_META_TRANSMISSION + 50, 60, 70, 85, 140, 188, 228, 266, 360, 442, 538, 842, 1024, MASA_MAX_BITS +#else 50, 60, 70, 85, 140, 180, 220, 256, 350, 432, 528, 832, 1024, MASA_MAX_BITS +#endif }; const int16_t masa_bits_LR_stereo[4] = diff --git a/lib_com/options.h b/lib_com/options.h index aecaf8747a1464a0df9d4328168d334a77aeb7ff..d4adc4c710b0de01f252549bccf12cd7faf4b281 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -164,7 +164,7 @@ #define FIX_416_ISM_BR_SWITCHING /* FhG: add missing CLDFB reconfig to ISM BR switching */ #define FIX_SP2A /* VA: Issue 412: Adjust threshold for the S_p2a feature in the tonal detector */ - +#define NOKIA_MASA_DESCRIPTIVE_META_TRANSMISSION /* Nokia: Contribution 40: Implements transmission and use of descriptive metadata. */ /* ################## End DEVELOPMENT switches ######################### */ /* clang-format on */ diff --git a/lib_dec/ivas_masa_dec.c b/lib_dec/ivas_masa_dec.c index 9cadbcc4fc1b3464baeb49a21d7e1a8e2bcd1132..a486bb65aac9e89cacfe8014a6d6912388e52235 100644 --- a/lib_dec/ivas_masa_dec.c +++ b/lib_dec/ivas_masa_dec.c @@ -72,6 +72,9 @@ static int16_t decode_lfe_to_total_energy_ratio( MCMASA_LFE_SYNTH_DATA_HANDLE hM static ivas_error ivas_masa_dec_config( Decoder_Struct *st_ivas ); +#ifdef NOKIA_MASA_DESCRIPTIVE_META_TRANSMISSION +static int16_t decode_masa_signaling( MASA_DECODER_HANDLE hMasa, uint16_t *bitstream, int16_t *index, const int32_t masa_bitrate, const int16_t nchan_transport ); +#endif /*-----------------------------------------------------------------------* * ivas_masa_decode() @@ -128,6 +131,17 @@ ivas_error ivas_masa_decode( if ( !st->bfi && ivas_total_brate > IVAS_SID_5k2 ) { +#ifdef NOKIA_MASA_DESCRIPTIVE_META_TRANSMISSION + if ( !( ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCMASA ) ) + { + *nb_bits_read += decode_masa_signaling( hMasa, st->bit_stream, &st->next_bit_pos, ivas_total_brate, st_ivas->nchan_transport ); + } + else + { + hMasa->config.numberOfDirections = 1; + hMasa->config.joinedSubframes = FALSE; + } +#else if ( !( ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCMASA ) ) { /* the number of MASA transport channels was read in ivas_dec_setup() */ @@ -159,6 +173,7 @@ ivas_error ivas_masa_decode( { hMasa->config.joinedSubframes = FALSE; } +#endif if ( st_ivas->mc_mode == MC_MODE_MCMASA ) { @@ -307,6 +322,16 @@ ivas_error ivas_masa_decode( if ( st_ivas->ivas_format == MASA_FORMAT && st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_EXTERNAL ) { create_masa_ext_out_meta( hMasa, hQMetaData, st_ivas->nchan_transport ); +#ifdef NOKIA_MASA_DESCRIPTIVE_META_TRANSMISSION + /* Copy transmitted descriptive metadata */ + hMasa->data.extOutMeta->descriptiveMeta.numberOfDirections = hMasa->data.descriptive_meta.numberOfDirections; + hMasa->data.extOutMeta->descriptiveMeta.numberOfChannels = hMasa->data.descriptive_meta.numberOfChannels; + hMasa->data.extOutMeta->descriptiveMeta.sourceFormat = hMasa->data.descriptive_meta.sourceFormat; + hMasa->data.extOutMeta->descriptiveMeta.transportDefinition = hMasa->data.descriptive_meta.transportDefinition; + hMasa->data.extOutMeta->descriptiveMeta.channelAngle = hMasa->data.descriptive_meta.channelAngle; + hMasa->data.extOutMeta->descriptiveMeta.channelDistance = hMasa->data.descriptive_meta.channelDistance; + hMasa->data.extOutMeta->descriptiveMeta.channelLayout = hMasa->data.descriptive_meta.channelLayout; +#endif } return error /* *nb_bits_read*/; @@ -481,6 +506,12 @@ static ivas_error ivas_masa_dec_config( { st_ivas->hQMetaData->q_direction[i].cfg.mc_ls_setup = ivas_mc_map_output_config_to_mc_ls_setup( st_ivas->transport_config ); } +#ifdef NOKIA_MASA_DESCRIPTIVE_META_TRANSMISSION + else if ( st_ivas->ivas_format == MASA_FORMAT && hMasa->data.descriptive_meta.sourceFormat == 0x2 ) /* MC source format */ + { + st_ivas->hQMetaData->q_direction[i].cfg.mc_ls_setup = ivas_masa_map_meta_channel_layout_to_mc_ls_setup( hMasa->data.descriptive_meta.channelLayout ); + } +#endif else { st_ivas->hQMetaData->q_direction[i].cfg.mc_ls_setup = MC_LS_SETUP_INVALID; @@ -1543,3 +1574,232 @@ static void create_masa_ext_out_meta( return; } + +#ifdef NOKIA_MASA_DESCRIPTIVE_META_TRANSMISSION +static uint16_t read_masa_bits( + uint16_t *bitstream, + int16_t *index, + const int16_t num_bits ) +{ + int16_t i; + uint16_t byteBuffer; + + byteBuffer = bitstream[( *index )--] << ( num_bits - 1 ); + for ( i = num_bits - 2; i >= 0; i-- ) + { + byteBuffer += bitstream[( *index )--] << i; + } + + return byteBuffer; +} + +static void reset_descriptive_metadata( + MASA_DECRIPTIVE_META *descMeta ) +{ + descMeta->sourceFormat = 0; + descMeta->transportDefinition = 0; + descMeta->channelAngle = 0; + descMeta->channelLayout = 0; + descMeta->channelDistance = 0; + descMeta->numberOfChannels = 0; + descMeta->numberOfDirections = 0; +} + +/*-----------------------------------------------------------------------* + * decode_masa_signaling() + * + * Decodes signaling for MASA format from bitstream + *-----------------------------------------------------------------------*/ + +/*! r: number of bits used for signaling */ +static int16_t decode_masa_signaling( + MASA_DECODER_HANDLE hMasa, + uint16_t *bitstream, + int16_t *index, + const int32_t masa_bitrate, + const int16_t nchan_transport ) +{ + int16_t num_bits_read = 0; + int16_t current_brate_idx; + int16_t is_two_dir_brate; + + reset_descriptive_metadata( &hMasa->data.descriptive_meta ); + + /* the number of MASA transport channels was read in ivas_dec_setup() */ + *index -= MASA_TRANSP_BITS; + num_bits_read += MASA_TRANSP_BITS; + hMasa->data.descriptive_meta.numberOfChannels = (uint8_t) nchan_transport - 1; + + /* read subframe mode */ + hMasa->config.joinedSubframes = (uint8_t) read_masa_bits( bitstream, index, MASA_SUBFRAME_BITS ); + num_bits_read += MASA_SUBFRAME_BITS; + + current_brate_idx = SIZE_IVAS_BRATE_TBL - 1; + while ( ivas_brate_tbl[current_brate_idx] > masa_bitrate ) + { + current_brate_idx--; + } + current_brate_idx -= ( SIZE_IVAS_BRATE_TBL - IVAS_NUM_ACTIVE_BRATES ); + + if ( hMasa->config.joinedSubframes ) + { + is_two_dir_brate = masa_twodir_bands_joined[current_brate_idx] > 0 ? TRUE : FALSE; + } + else + { + is_two_dir_brate = masa_twodir_bands[current_brate_idx] > 0 ? TRUE : FALSE; + } + + /* Read number of directions if bitrate supports it */ + if ( is_two_dir_brate ) + { + hMasa->config.numberOfDirections = (uint8_t) read_masa_bits( bitstream, index, 1 ) + 1; + num_bits_read += 1; + } + else + { + hMasa->config.numberOfDirections = 1; + } + hMasa->data.descriptive_meta.numberOfDirections = hMasa->config.numberOfDirections - 1; + + /* Decode rest of descriptive metadata bits depending on the bitrate. This is handled with levels of detail. */ + if ( masa_bitrate >= MASA_DESC_META_LEVEL3_BRATE ) + { + /* Level 3: Send full descriptive metadata */ + /* Decode source format */ + hMasa->data.descriptive_meta.sourceFormat = (uint8_t) read_masa_bits( bitstream, index, 2 ); + num_bits_read += 2; + + if ( hMasa->data.descriptive_meta.sourceFormat == 0x2 ) /* MC source format path */ + { + /* Decode channel layout */ + hMasa->data.descriptive_meta.channelLayout = (uint8_t) read_masa_bits( bitstream, index, 3 ); + num_bits_read += 3; + } + else /* Other source formats */ + { + /* Decode transport definition */ + hMasa->data.descriptive_meta.transportDefinition = (uint8_t) read_masa_bits( bitstream, index, 3 ); + num_bits_read += 3; + + /* Decode channel angle */ + hMasa->data.descriptive_meta.channelAngle = (uint8_t) read_masa_bits( bitstream, index, 3 ); + num_bits_read += 3; + + if ( hMasa->data.descriptive_meta.sourceFormat != 0x3 ) /* If not in Ambisonics source format path */ + { + /* Decode channel distance */ + hMasa->data.descriptive_meta.channelDistance = (uint8_t) read_masa_bits( bitstream, index, 6 ); + num_bits_read += 6; + } + } + } + else if ( masa_bitrate >= MASA_DESC_META_LEVEL2_BRATE ) + { + /* Level 2: Reduce transport description options and accuracy */ + + /* Decode source format */ + hMasa->data.descriptive_meta.sourceFormat = (uint8_t) read_masa_bits( bitstream, index, 2 ); + num_bits_read += 2; + + if ( hMasa->data.descriptive_meta.sourceFormat == 0x2 ) /* MC source format path */ + { + /* Decode channel layout */ + hMasa->data.descriptive_meta.channelLayout = (uint8_t) read_masa_bits( bitstream, index, 3 ); + num_bits_read += 3; + } + else /* Other source formats */ + { + /* Decode reduced transport definition */ + uint16_t reducedTransportDefinition; + reducedTransportDefinition = read_masa_bits( bitstream, index, 2 ); + num_bits_read += 2; + + if ( reducedTransportDefinition == 3 ) + { + hMasa->data.descriptive_meta.transportDefinition = 0x7; + } + else if ( reducedTransportDefinition == 2 ) + { + hMasa->data.descriptive_meta.transportDefinition = 0x3; + } + else + { + hMasa->data.descriptive_meta.transportDefinition = (uint8_t) reducedTransportDefinition; + } + + /* Decode reduced channel angle if there is a directional pattern */ + if ( reducedTransportDefinition == 2 ) + { + hMasa->data.descriptive_meta.channelAngle = (uint8_t) read_masa_bits( bitstream, index, 1 ); + num_bits_read += 1; + } + + if ( hMasa->data.descriptive_meta.sourceFormat != 0x3 ) /* If not in Ambisonics source format path */ + { + /* Decode reduced channel distance */ + uint16_t channelDistance5bit; + channelDistance5bit = read_masa_bits( bitstream, index, 5 ); + num_bits_read += 5; + + if ( channelDistance5bit < 3 ) + { + hMasa->data.descriptive_meta.channelDistance = (uint8_t) channelDistance5bit; + } + else if ( channelDistance5bit == 31 ) + { + hMasa->data.descriptive_meta.channelDistance = 63; + } + else + { + hMasa->data.descriptive_meta.channelDistance = (uint8_t) ( ( channelDistance5bit - 3 ) * 2 + 3 ); + } + } + } + } + else + { + /* Level 1: Send minimal data */ + uint16_t is_mc_source_format; + + /* Decode if the source format is multichannel or any other */ + is_mc_source_format = read_masa_bits( bitstream, index, 1 ); + if ( is_mc_source_format ) + { + hMasa->data.descriptive_meta.sourceFormat = 0x2; + } + else + { + hMasa->data.descriptive_meta.sourceFormat = 0x0; + } + num_bits_read += 1; + + if ( is_mc_source_format ) + { + /* Decode channel layout */ + hMasa->data.descriptive_meta.channelLayout = (uint8_t) read_masa_bits( bitstream, index, 3 ); + num_bits_read += 3; + } + else + { + /* Use 1 bit to signal if the transport is binaural and there are two transport channels */ + if ( nchan_transport == 2 ) + { + uint16_t is_binaural_transport = 0; + is_binaural_transport = read_masa_bits( bitstream, index, 1 ); + num_bits_read += 1; + if ( is_binaural_transport ) + { + hMasa->data.descriptive_meta.transportDefinition = 0x7; + } + else + { + hMasa->data.descriptive_meta.transportDefinition = 0x0; + } + } + } + } + + return num_bits_read; +} +#endif diff --git a/lib_dec/ivas_stat_dec.h b/lib_dec/ivas_stat_dec.h index 4a17c75dda9f42d5fffbded309972d8817f92ff6..8fa62960dca02213e926733a79c7f7626b7df9fb 100644 --- a/lib_dec/ivas_stat_dec.h +++ b/lib_dec/ivas_stat_dec.h @@ -1114,6 +1114,9 @@ typedef struct ivas_masa_decoder_data_struct MASA_DECODER_EXT_OUT_META *extOutMeta; float dir_decode_quality; +#ifdef NOKIA_MASA_DESCRIPTIVE_META_TRANSMISSION + MASA_DECRIPTIVE_META descriptive_meta; +#endif } MASA_DECODER_DATA; diff --git a/lib_enc/ivas_masa_enc.c b/lib_enc/ivas_masa_enc.c index 2a21a667e941be7447a36cd81869bf394896a49e..4342f1acc3af567c7cfcf214ba2cc82c78096101 100644 --- a/lib_enc/ivas_masa_enc.c +++ b/lib_enc/ivas_masa_enc.c @@ -75,6 +75,10 @@ static void detect_framing_async( MASA_ENCODER_HANDLE hMasa ); static void masa_metadata_direction_alignment( MASA_ENCODER_HANDLE hMasa ); #endif +#ifdef NOKIA_MASA_DESCRIPTIVE_META_TRANSMISSION +static int16_t encode_masa_signaling( BSTR_ENC_HANDLE hMetaData, MASA_ENCODER_HANDLE hMasa, const int32_t masa_bitrate, const int16_t nchan_transport ); +#endif + /*-----------------------------------------------------------------------* * Local constants *-----------------------------------------------------------------------*/ @@ -272,6 +276,9 @@ ivas_error ivas_masa_encode( if ( ivas_format == MASA_FORMAT ) { +#ifdef NOKIA_MASA_DESCRIPTIVE_META_TRANSMISSION + hQMetaData->metadata_max_bits -= encode_masa_signaling( hMetaData, hMasa, ivas_total_brate, nchan_transport ); +#else /* write the number of MASA transport channels */ push_next_indice( hMetaData, nchan_transport - 1, MASA_TRANSP_BITS ); hQMetaData->metadata_max_bits -= MASA_TRANSP_BITS; @@ -287,6 +294,7 @@ ivas_error ivas_masa_encode( /* write subframe mode */ push_next_indice( hMetaData, hQMetaData->q_direction[0].cfg.nblocks == 1 ? 1 : 0, MASA_SUBFRAME_BITS ); hQMetaData->metadata_max_bits -= MASA_SUBFRAME_BITS; +#endif } if ( ivas_format == MC_FORMAT ) @@ -574,6 +582,12 @@ ivas_error ivas_masa_enc_config( { hQMetaData->q_direction[i].cfg.mc_ls_setup = st_ivas->hEncoderConfig->mc_input_setup; } +#ifdef NOKIA_MASA_DESCRIPTIVE_META_TRANSMISSION + else if ( ivas_format == MASA_FORMAT && hMasa->masaMetadata.descriptive_meta.sourceFormat == 0x2 ) /* MC source format */ + { + st_ivas->hQMetaData->q_direction[i].cfg.mc_ls_setup = ivas_masa_map_meta_channel_layout_to_mc_ls_setup( hMasa->masaMetadata.descriptive_meta.channelLayout ); + } +#endif else { /* Just to be sure that this default value is maintained */ @@ -1700,6 +1714,207 @@ void ivas_masa_enc_reconfigure( return; } +#ifdef NOKIA_MASA_DESCRIPTIVE_META_TRANSMISSION + +/*-----------------------------------------------------------------------* + * encode_masa_signaling() + * + * Encodes signaling for MASA format to bitstream + *-----------------------------------------------------------------------*/ + +/*! r: number of bits used for signaling */ +static int16_t encode_masa_signaling( + BSTR_ENC_HANDLE hMetaData, + MASA_ENCODER_HANDLE hMasa, + const int32_t masa_bitrate, + const int16_t nchan_transport ) +{ + int16_t num_bits_used = 0; + int16_t current_brate_idx; + int16_t is_two_dir_brate; + + /* Write the number of MASA transport channels. This is always written for MASA. */ + push_next_indice( hMetaData, nchan_transport - 1, MASA_TRANSP_BITS ); + num_bits_used += MASA_TRANSP_BITS; + + /* Write subframe mode */ + push_next_indice( hMetaData, hMasa->config.joinedSubframes == TRUE ? 1 : 0, MASA_SUBFRAME_BITS ); + num_bits_used += MASA_SUBFRAME_BITS; + + current_brate_idx = SIZE_IVAS_BRATE_TBL - 1; + while ( ivas_brate_tbl[current_brate_idx] > masa_bitrate ) + { + current_brate_idx--; + } + current_brate_idx -= ( SIZE_IVAS_BRATE_TBL - IVAS_NUM_ACTIVE_BRATES ); + + if ( hMasa->config.joinedSubframes ) + { + is_two_dir_brate = masa_twodir_bands_joined[current_brate_idx] > 0 ? TRUE : FALSE; + } + else + { + is_two_dir_brate = masa_twodir_bands[current_brate_idx] > 0 ? TRUE : FALSE; + } + + /* Signal number of directions if bitrate allows it */ + if ( is_two_dir_brate ) + { + push_next_indice( hMetaData, hMasa->config.numberOfDirections - 1, 1 ); + num_bits_used += 1; + } + + /* Write rest of descriptive metadata bits depending on the bitrate. This is handled with levels of detail. */ + if ( masa_bitrate >= MASA_DESC_META_LEVEL3_BRATE ) + { + /* Level 3: Send full descriptive metadata */ + /* Encode source format */ + push_next_indice( hMetaData, hMasa->masaMetadata.descriptive_meta.sourceFormat, 2 ); + num_bits_used += 2; + + if ( hMasa->masaMetadata.descriptive_meta.sourceFormat == 0x2 ) /* MC source format path */ + { + /* Encode channel layout */ + push_next_indice( hMetaData, hMasa->masaMetadata.descriptive_meta.channelLayout, 3 ); + num_bits_used += 3; + } + else /* Other source formats */ + { + /* Encode transport definition */ + push_next_indice( hMetaData, hMasa->masaMetadata.descriptive_meta.transportDefinition, 3 ); + num_bits_used += 3; + + /* Encode channel angle */ + push_next_indice( hMetaData, hMasa->masaMetadata.descriptive_meta.channelAngle, 3 ); + num_bits_used += 3; + + if ( hMasa->masaMetadata.descriptive_meta.sourceFormat != 0x3 ) /* If not in Ambisonics source format path */ + { + /* Encode channel distance */ + push_next_indice( hMetaData, hMasa->masaMetadata.descriptive_meta.channelDistance, 6 ); + num_bits_used += 6; + } + } + } + else if ( masa_bitrate >= MASA_DESC_META_LEVEL2_BRATE ) + { + /* Level 2: Reduce transport description options and accuracy + * With Default/Other or Microphone Grid source format, uses 9-10 bits + * With MC source format, uses 5 bits + * With Ambisonics source format, uses 4-5 bits */ + + /* Encode source format */ + push_next_indice( hMetaData, hMasa->masaMetadata.descriptive_meta.sourceFormat, 2 ); + num_bits_used += 2; + + if ( hMasa->masaMetadata.descriptive_meta.sourceFormat == 0x2 ) /* MC source format path */ + { + /* Encode channel layout */ + push_next_indice( hMetaData, hMasa->masaMetadata.descriptive_meta.channelLayout, 3 ); + num_bits_used += 3; + } + else /* Other source formats */ + { + /* Encode reduced transport definition with two bits. Non-fitting patterns are converted to 0. + * This is coded as: + * 0: Unknown/Other + * 1: Omni + * 2: Cardioid + * 3: Binaural */ + int16_t reducedTransportDefinition; + + if ( hMasa->masaMetadata.descriptive_meta.transportDefinition == 0x1 ) + { + reducedTransportDefinition = 1; + } + else if ( hMasa->masaMetadata.descriptive_meta.transportDefinition == 0x3 ) + { + reducedTransportDefinition = 2; + } + else if ( hMasa->masaMetadata.descriptive_meta.transportDefinition == 0x7 ) + { + reducedTransportDefinition = 3; + } + else + { + reducedTransportDefinition = 0; + } + + push_next_indice( hMetaData, reducedTransportDefinition, 2 ); + num_bits_used += 2; + + /* Encode channel angle as unspecified on 90° if there is a directive pattern */ + if ( reducedTransportDefinition == 2 ) + { + int16_t is90degChannelAngle; + is90degChannelAngle = hMasa->masaMetadata.descriptive_meta.channelAngle == 0x1 ? 1 : 0; + push_next_indice( hMetaData, is90degChannelAngle, 1 ); + num_bits_used += 1; + } + + if ( hMasa->masaMetadata.descriptive_meta.sourceFormat != 0x3 ) /* If not in Ambisonics source format path */ + { + /* Encode channel distance but reduce to use of 5 bits in total while preserving the 4 special cases. The + * result is following: + * 0-2: as is for special values + * 3-30: use every second value from original bits, non-matching values round down to previous unless over 58 + * 31: as is (but some values will round up here) */ + int16_t channelDistance5bit; + if ( hMasa->masaMetadata.descriptive_meta.channelDistance < 3 ) + { + channelDistance5bit = hMasa->masaMetadata.descriptive_meta.channelDistance; + } + else if ( hMasa->masaMetadata.descriptive_meta.channelDistance > 58 ) + { + channelDistance5bit = 31; + } + else + { + channelDistance5bit = ( hMasa->masaMetadata.descriptive_meta.channelDistance - 3 ) / 2 + 3; /* Intentional truncation */ + } + push_next_indice( hMetaData, channelDistance5bit, 5 ); + num_bits_used += 5; + } + } + } + else + { + /* Level 1: Send minimal data */ + int16_t is_mc_source_format; + + /* Signal if the source format is multichannel or any other */ + is_mc_source_format = hMasa->masaMetadata.descriptive_meta.sourceFormat == 0x2 ? 1 : 0; + push_next_indice( hMetaData, is_mc_source_format, 1 ); + num_bits_used += 1; + + if ( is_mc_source_format ) + { + /* Encode channel layout */ + push_next_indice( hMetaData, hMasa->masaMetadata.descriptive_meta.channelLayout, 3 ); + num_bits_used += 3; + } + else + { + /* Use 1 bit to signal if the transport is binaural and there are two transport channels */ + if ( nchan_transport == 2 ) + { + int16_t is_binaural_transport = 0; + if ( hMasa->masaMetadata.descriptive_meta.sourceFormat == 0x0 || hMasa->masaMetadata.descriptive_meta.sourceFormat == 0x1 ) + { + if ( hMasa->masaMetadata.descriptive_meta.transportDefinition == 0x7 ) + { + is_binaural_transport = 1; + } + } + push_next_indice( hMetaData, is_binaural_transport, 1 ); + num_bits_used += 1; + } + } + } + + return num_bits_used; +} +#endif /*-------------------------------------------------------------------*