diff --git a/lib_com/options.h b/lib_com/options.h index d4ea004209494f5d5b62693445bdf53edf39afad..21c7885e4d4450b58c66da37ec298f0eb72735dd 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -151,12 +151,10 @@ #define FIX_382_MASA_META_FRAMING_ASYNC /* Nokia: Issue 382: detect potential MASA metadata framing offset */ #define FIX_386_CORECODER_RECONFIG /* VA: Issue 386: Resolve ToDo comments in CoreCoder reconfig. */ - #define SBA2MONO /* FhG: Issue 365: Adapt processing of SBA mono output to be in line with stereo output (less delay, lower complexity) */ #define FIX_379_EXT_METADATA /* Eri: Extended metadata issues */ #define FIX_379_ANGLE /* Eri: Extended metadata issues related to angle structure */ - #define NOKIA_PARAMBIN_REQULARIZATION /* Nokia: Contribution - Configured reqularization factor for parametric binauralizer. */ #define NOKIA_ADAPTIVE_BINAURAL_PROTOS /* Nokia: Contribution 28: Adaptive binaural prototypes */ #define NOKIA_ADAPTIVE_BINAURAL_PROTOS_OPT /* Nokia: enable adaptive binaural prototype complexity optimizations */ @@ -167,7 +165,9 @@ #define FIX_ISM_DTX_CLICKS /* FhG: fix for clicks in ISM DTX for inactive to active TCX transitions */ -#define ISSUE_24_CLEANUP_MCT_LFE /* Issue 24: Cleanup LFE path withing MCT */ +#define ISSUE_24_CLEANUP_MCT_LFE /* Issue 24: Cleanup LFE path withing MCT */ + +#define FIX_398_MASA_DIRECTION_ALIGNMENT /* Nokia: Issue 398: in 2dir MASA, dynamically adjust directions to be consistent */ #define FIX_401_DIRAC_RENDERER_META_READ_INDICES /* Nokia: Issue 401: Fix metadata reading indices in DirAC renderer. */ #define FIX_406_IVAS_POSITION /* Eri: Issue 406: Unify IVAS_POSITION to use IVAS_VECTOR3 instead */ diff --git a/lib_enc/ivas_masa_enc.c b/lib_enc/ivas_masa_enc.c index fbb7af9ab4a3b42566b82e3c6f7fe953251b40b6..5c6e596cd240f2cbc532d021c1af815e2910aff0 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 FIX_398_MASA_DIRECTION_ALIGNMENT +static void masa_metadata_direction_alignment( MASA_ENCODER_HANDLE hMasa ); +#endif + /*-----------------------------------------------------------------------* * Local constants *-----------------------------------------------------------------------*/ @@ -155,6 +159,13 @@ ivas_error ivas_masa_enc_open( hMasa->data.sync_state.frame_mode = MASA_FRAME_4SF; #endif +#ifdef FIX_398_MASA_DIRECTION_ALIGNMENT + set_zero( hMasa->data.dir_align_state.previous_azi_dir1, MASA_FREQUENCY_BANDS ); + set_zero( hMasa->data.dir_align_state.previous_ele_dir1, MASA_FREQUENCY_BANDS ); + set_zero( hMasa->data.dir_align_state.previous_azi_dir2, MASA_FREQUENCY_BANDS ); + set_zero( hMasa->data.dir_align_state.previous_ele_dir2, MASA_FREQUENCY_BANDS ); +#endif + st_ivas->hMasa = hMasa; return error; @@ -525,8 +536,13 @@ ivas_error ivas_masa_enc_config( if ( ivas_format == MASA_FORMAT ) { +#ifdef FIX_398_MASA_DIRECTION_ALIGNMENT + masa_metadata_direction_alignment( hMasa ); +#endif + #ifdef FIX_382_MASA_META_FRAMING_ASYNC detect_framing_async( hMasa ); /* detect the offset, set 1sf/4sf mode based on this. potentially also shift the metadata using a history buffer */ + if ( hMasa->data.sync_state.frame_mode == MASA_FRAME_1SF && hMasa->data.sync_state.prev_offset != 0 ) { /* average over sub-frames */ @@ -2198,3 +2214,168 @@ static void detect_framing_async( return; } #endif + + +#ifdef FIX_398_MASA_DIRECTION_ALIGNMENT +/*-------------------------------------------------------------------* + * masa_metadata_direction_alignment() + * + * In 2dir MASA metadata, determine the ordering of the directional + * fields such that the azi/ele change across time is minimized. + *-------------------------------------------------------------------*/ + +static void masa_metadata_direction_alignment( + MASA_ENCODER_HANDLE hMasa /* i/o: MASA encoder handle */ +) +{ + uint8_t band, n_dirs; + + MASA_DIR_ALIGN_HANDLE hAlignState; + MASA_METADATA_HANDLE hMeta; + + hAlignState = &( hMasa->data.dir_align_state ); + hMeta = &( hMasa->masaMetadata ); + + n_dirs = hMeta->descriptive_meta.numberOfDirections + 1; /* 1-based */ + for ( band = 0; band < MASA_FREQUENCY_BANDS; band++ ) + { + uint8_t sf; + float diff_swap, diff_no_swap; + + /* trade 2*(cos+sin) against storing the values between frames */ + float prev_ele_dir1_sin, prev_ele_dir2_sin; + float prev_ele_dir1_cos, prev_ele_dir2_cos; + + prev_ele_dir1_sin = sinf( hAlignState->previous_ele_dir1[band] ); + prev_ele_dir2_sin = sinf( hAlignState->previous_ele_dir2[band] ); + + prev_ele_dir1_cos = cosf( hAlignState->previous_ele_dir1[band] ); + prev_ele_dir2_cos = cosf( hAlignState->previous_ele_dir2[band] ); + + for ( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ ) + { + float azi_rad1, ele_rad1; + float azi_rad2, ele_rad2; + float cos_ele1, cos_ele2; + float sin_ele1, sin_ele2; + + azi_rad1 = hMeta->directional_meta[0].azimuth[sf][band] * PI_OVER_180; + ele_rad1 = hMeta->directional_meta[0].elevation[sf][band] * PI_OVER_180; + + if ( n_dirs > 1 ) + { + azi_rad2 = hMeta->directional_meta[1].azimuth[sf][band] * PI_OVER_180; + ele_rad2 = hMeta->directional_meta[1].elevation[sf][band] * PI_OVER_180; + + /* quick checks to detect constant data and earlier flip */ + if ( fabsf( azi_rad1 - hAlignState->previous_azi_dir1[band] ) < EPSILON && + fabsf( azi_rad2 - hAlignState->previous_azi_dir2[band] ) < EPSILON && + fabsf( ele_rad1 - hAlignState->previous_ele_dir1[band] ) < EPSILON && + fabsf( ele_rad2 - hAlignState->previous_ele_dir2[band] ) < EPSILON ) + { + diff_swap = 1.0f; + diff_no_swap = 0.0f; + /* cached values that will be used for the short-cuts and over-written by the real computations, if done */ + sin_ele1 = prev_ele_dir1_sin; + sin_ele2 = prev_ele_dir2_sin; + cos_ele1 = prev_ele_dir1_cos; + cos_ele2 = prev_ele_dir2_cos; + } + else if ( fabsf( azi_rad1 - hAlignState->previous_azi_dir2[band] ) < EPSILON && + fabsf( azi_rad2 - hAlignState->previous_azi_dir1[band] ) < EPSILON && + fabsf( ele_rad1 - hAlignState->previous_ele_dir2[band] ) < EPSILON && + fabsf( ele_rad2 - hAlignState->previous_ele_dir1[band] ) < EPSILON ) + { + diff_swap = 0.0f; + diff_no_swap = 1.0f; + /* cached values that will be used for the short-cuts and over-written by the real computations, if done */ + sin_ele1 = prev_ele_dir2_sin; + sin_ele2 = prev_ele_dir1_sin; + cos_ele1 = prev_ele_dir2_cos; + cos_ele2 = prev_ele_dir1_cos; + } + else + { + /* angular distance of the two vectors */ + /* pre-compute values for re-use */ + sin_ele1 = sinf( ele_rad1 ); + sin_ele2 = sinf( ele_rad2 ); + + cos_ele1 = cosf( ele_rad1 ); + cos_ele2 = cosf( ele_rad2 ); + + diff_no_swap = acosf( cos_ele1 * prev_ele_dir1_cos * cosf( azi_rad1 - hAlignState->previous_azi_dir1[band] ) + sin_ele1 * prev_ele_dir1_sin ) + + acosf( cos_ele2 * prev_ele_dir2_cos * cosf( azi_rad2 - hAlignState->previous_azi_dir2[band] ) + sin_ele2 * prev_ele_dir2_sin ); + + diff_swap = acosf( cos_ele1 * prev_ele_dir2_cos * cosf( azi_rad1 - hAlignState->previous_azi_dir2[band] ) + sin_ele1 * prev_ele_dir2_sin ) + + acosf( cos_ele2 * prev_ele_dir1_cos * cosf( azi_rad2 - hAlignState->previous_azi_dir1[band] ) + sin_ele2 * prev_ele_dir1_sin ); + } + } + else + { + /* 1dir */ + sin_ele1 = sinf( ele_rad1 ); + cos_ele1 = cosf( ele_rad1 ); + + azi_rad2 = 0.0f; + ele_rad2 = 0.0f; + + sin_ele2 = 0.0f; /* sin(0) */ + cos_ele2 = 1.0f; /* cos(0) */ + + diff_swap = 1.0f; + diff_no_swap = 0.0f; + } + + if ( n_dirs > 1 && diff_no_swap > diff_swap ) + { + /* swap the metadata of the two directions in this TF-tile */ + float tmp_val; + tmp_val = hMeta->directional_meta[0].azimuth[sf][band]; + hMeta->directional_meta[0].azimuth[sf][band] = hMeta->directional_meta[1].azimuth[sf][band]; + hMeta->directional_meta[1].azimuth[sf][band] = tmp_val; + + tmp_val = hMeta->directional_meta[0].elevation[sf][band]; + hMeta->directional_meta[0].elevation[sf][band] = hMeta->directional_meta[1].elevation[sf][band]; + hMeta->directional_meta[1].elevation[sf][band] = tmp_val; + + tmp_val = hMeta->directional_meta[0].energy_ratio[sf][band]; + hMeta->directional_meta[0].energy_ratio[sf][band] = hMeta->directional_meta[1].energy_ratio[sf][band]; + hMeta->directional_meta[1].energy_ratio[sf][band] = tmp_val; + + tmp_val = hMeta->directional_meta[0].spread_coherence[sf][band]; + hMeta->directional_meta[0].spread_coherence[sf][band] = hMeta->directional_meta[1].spread_coherence[sf][band]; + hMeta->directional_meta[1].spread_coherence[sf][band] = tmp_val; + + hAlignState->previous_azi_dir1[band] = azi_rad2; + hAlignState->previous_ele_dir1[band] = ele_rad2; + + hAlignState->previous_azi_dir2[band] = azi_rad1; + hAlignState->previous_ele_dir2[band] = ele_rad1; + + prev_ele_dir1_cos = cos_ele2; + prev_ele_dir1_sin = sin_ele2; + + prev_ele_dir2_cos = cos_ele1; + prev_ele_dir2_sin = sin_ele1; + } + else + { + hAlignState->previous_azi_dir1[band] = azi_rad1; + hAlignState->previous_ele_dir1[band] = ele_rad1; + + hAlignState->previous_azi_dir2[band] = azi_rad2; + hAlignState->previous_ele_dir2[band] = ele_rad2; + + prev_ele_dir1_cos = cos_ele1; + prev_ele_dir1_sin = sin_ele1; + + prev_ele_dir2_cos = cos_ele2; + prev_ele_dir2_sin = sin_ele2; + } + } /* sf */ + } /* band */ + + return; +} +#endif diff --git a/lib_enc/ivas_stat_enc.h b/lib_enc/ivas_stat_enc.h index 6638a8948893cd39c5278f7d59122448c75a1237..424e6b0c02b328f817a350663ac671e3684585a5 100644 --- a/lib_enc/ivas_stat_enc.h +++ b/lib_enc/ivas_stat_enc.h @@ -740,6 +740,18 @@ typedef struct ivas_param_mc_enc_data_structure * MASA encoder structures *----------------------------------------------------------------------------------*/ +#ifdef FIX_398_MASA_DIRECTION_ALIGNMENT +typedef struct ivas_masa_dir_align_struct +{ + float previous_azi_dir1[MASA_FREQUENCY_BANDS]; + float previous_ele_dir1[MASA_FREQUENCY_BANDS]; + + float previous_azi_dir2[MASA_FREQUENCY_BANDS]; + float previous_ele_dir2[MASA_FREQUENCY_BANDS]; + +} MASA_DIR_ALIGN_STATE, *MASA_DIR_ALIGN_HANDLE; +#endif + #ifdef FIX_382_MASA_META_FRAMING_ASYNC /* structure storing MASA framing sync detection and compensation data */ typedef struct ivas_masa_sync_struct @@ -748,6 +760,7 @@ typedef struct ivas_masa_sync_struct uint8_t prev_sim_stop; uint8_t prev_offset; MASA_FRAME_MODE frame_mode; + } MASA_SYNC_STATE, *MASA_SYNC_HANDLE; #endif @@ -773,6 +786,11 @@ typedef struct ivas_masa_encoder_data_struct #ifdef FIX_382_MASA_META_FRAMING_ASYNC MASA_SYNC_STATE sync_state; #endif + +#ifdef FIX_398_MASA_DIRECTION_ALIGNMENT + MASA_DIR_ALIGN_STATE dir_align_state; +#endif + } MASA_ENCODER_DATA; typedef struct ivas_masa_encoder_struct