From 478ae56f8be658f8556a637006ce95a26b6db4f2 Mon Sep 17 00:00:00 2001 From: Tapani Pihlajakuja Date: Thu, 13 Apr 2023 08:23:31 +0300 Subject: [PATCH] Implements contribution 40 - MASA descriptive metadata transmission. --- lib_com/ivas_cnst.h | 6 + lib_com/ivas_masa_com.c | 31 +++++ lib_com/ivas_prot.h | 7 ++ lib_com/ivas_rom_com.c | 4 + lib_com/options.h | 2 + lib_dec/ivas_masa_dec.c | 260 ++++++++++++++++++++++++++++++++++++++++ lib_dec/ivas_stat_dec.h | 3 + lib_enc/ivas_masa_enc.c | 215 +++++++++++++++++++++++++++++++++ 8 files changed, 528 insertions(+) diff --git a/lib_com/ivas_cnst.h b/lib_com/ivas_cnst.h index d7674b4373..e9c13a7a6c 100644 --- a/lib_com/ivas_cnst.h +++ b/lib_com/ivas_cnst.h @@ -1204,6 +1204,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 3a53b2c682..2b5b65633b 100644 --- a/lib_com/ivas_masa_com.c +++ b/lib_com/ivas_masa_com.c @@ -415,3 +415,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 21ea995a84..378fd4f0b7 100755 --- a/lib_com/ivas_prot.h +++ b/lib_com/ivas_prot.h @@ -4604,6 +4604,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 f04538c479..abf16424b7 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 a6a4b4944d..de2aa4bc0a 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -164,6 +164,8 @@ #define FIX_390_EXT_REND_MASA_META_COPY /* Nokia: Issue 390: Fixes MASA metadata copying to renderer. */ #define FIX_392_LATE_REVERB /* DLB : Issue 392: keep late reverb by default off when output config is not BINAURAL_ROOM*/ +#define NOKIA_MASA_DESCRIPTIVE_META_TRANSMISSION /* Nokia: Implements transmission and use of descriptive metadata. */ + /* ################## End DEVELOPMENT switches ######################### */ /* clang-format on */ #endif diff --git a/lib_dec/ivas_masa_dec.c b/lib_dec/ivas_masa_dec.c index 3c7e490cbc..9a5281ed3a 100644 --- a/lib_dec/ivas_masa_dec.c +++ b/lib_dec/ivas_masa_dec.c @@ -76,6 +76,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() @@ -132,6 +135,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() */ @@ -163,6 +177,7 @@ ivas_error ivas_masa_decode( { hMasa->config.joinedSubframes = FALSE; } +#endif if ( st_ivas->mc_mode == MC_MODE_MCMASA ) { @@ -312,6 +327,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 } #endif @@ -493,6 +518,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; @@ -1561,3 +1592,232 @@ static void create_masa_ext_out_meta( return; } #endif + +#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 3bfd806bdf..4ee7d1dfb4 100644 --- a/lib_dec/ivas_stat_dec.h +++ b/lib_dec/ivas_stat_dec.h @@ -1123,6 +1123,9 @@ typedef struct ivas_masa_decoder_data_struct MASA_DECODER_EXT_OUT_META *extOutMeta; #endif 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 fbb7af9ab4..763cb6e6ad 100644 --- a/lib_enc/ivas_masa_enc.c +++ b/lib_enc/ivas_masa_enc.c @@ -73,6 +73,10 @@ static uint8_t are_masa_subframes_similar( const MASA_METADATA_HANDLE frame1, co static void detect_framing_async( 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 *-----------------------------------------------------------------------*/ @@ -290,6 +294,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; @@ -305,6 +312,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 ) @@ -612,6 +620,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 */ @@ -1797,6 +1811,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 #ifdef FIX_382_MASA_META_FRAMING_ASYNC -- GitLab