diff --git a/apps/renderer.c b/apps/renderer.c index 8682232fa0f3a0f2b32e2bdce8ba83e31319da22..47159892db354a6bf4dce349ffde54d251d86dd5 100644 --- a/apps/renderer.c +++ b/apps/renderer.c @@ -2432,6 +2432,9 @@ static void convertOutputBuffer( int16_t *intBuffer ) { int16_t chnl, smpl, i; +#ifdef FIX_REND_ROUNDING + float temp; +#endif i = 0; @@ -2439,7 +2442,21 @@ static void convertOutputBuffer( { for ( chnl = 0; chnl < numChannels; ++chnl ) { +#ifdef FIX_REND_ROUNDING + temp = floatBuffer[chnl * numSamplesPerChannel + smpl]; + temp = (float) floor( temp + 0.5f ); + if ( temp > MAX16B_FLT ) + { + temp = MAX16B_FLT; + } + else if ( temp < MIN16B_FLT ) + { + temp = MIN16B_FLT; + } + intBuffer[i] = (int16_t) temp; +#else intBuffer[i] = (int16_t) roundf( floatBuffer[chnl * numSamplesPerChannel + smpl] ); +#endif ++i; } diff --git a/lib_com/options.h b/lib_com/options.h index 8a84da5d9f5375155690d2e4d2f53caa446133d5..3446d2e182db3c23affbf9fa1448a8d430371729 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -150,6 +150,9 @@ #define FIX_ITD /* Contribution 16: TD renderer ITD improvement and code cleanup */ #define BRATE_SWITCHING_RENDERING /* Bitrate switching changes related to the renderers */ #define FIX_ISM_DECODER_PRINTOUT /* Issue 229: fix ISM decoder printout */ +#define FIX_REND_ROUNDING /* Issue 195: Align float to int16 conversion in renderer with decoder */ +#define FIX_REND_MONO_DMX /* Issue 195: Fix mono downmix coefficients in decoder and renderer */ +#define FIX_REND_ROT_MC_BIN /* Issue 195: Fix wrong EFAP handle passed to renderer, resulting in no rotation for BINAURAL_ROOM output */ #define FIX_ITD_CNG /* Eri Contribution 11: Fix for CNG ITD */ #define FIX_VBR_COMPLEXITY /* Issue 234: fix extremely high complexity numbers for IVAS EVS mode */ #define FIX_ISM_INACTIVE_BITS /* Issue 230: fix bitbudget distribution in inactive frames in ISM format */ diff --git a/lib_rend/ivas_rom_rend.c b/lib_rend/ivas_rom_rend.c index cf0c7c69a94de9018ab5ebf56bf0ea00a1bb4814..4f647922c59e5640e517b9ecf1518e59b89c446b 100644 --- a/lib_rend/ivas_rom_rend.c +++ b/lib_rend/ivas_rom_rend.c @@ -361,10 +361,20 @@ const uint32_t ls_LFE_last_idx_CICP19[12] = { 0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, /* Downmix matrices */ const float ls_conversion_cicpX_mono[12][1] = { +#ifdef FIX_REND_MONO_DMX {1.00000000f}, {1.00000000f}, {1.00000000f}, {1.00000000f}, + {0.79999995f}, + {0.79999995f}, + {0.79999995f}, + {0.79999995f}, + {0.849999964f}, + {0.849999964f}, + {0.849999964f}, + {0.849999964f} +#else {1.00000000f}, {1.00000000f}, {1.00000000f}, @@ -373,6 +383,11 @@ const float ls_conversion_cicpX_mono[12][1] = {1.00000000f}, {1.00000000f}, {1.00000000f}, + {1.00000000f}, + {1.00000000f}, + {1.00000000f}, + {1.00000000f}, +#endif }; const float ls_conversion_cicpX_stereo[12][2] = diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 2764aa6a10b4a8ed4f29fb9d6c502d58f469b344..80988d734697a827a02c222189cb7240b1c7772e 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -1198,6 +1198,11 @@ static ivas_error initMcPanGainsWithMonoOut( { int16_t i; int16_t numInChannels; +#ifdef FIX_REND_MONO_DMX + int16_t readIdx; + int16_t writeIdx; + bool skipSideSpeakers; +#endif ivas_error error; if ( ( error = getRendInputNumChannels( inputMc, &numInChannels ) ) != IVAS_ERR_OK ) @@ -1205,12 +1210,44 @@ static ivas_error initMcPanGainsWithMonoOut( return error; } +#ifdef FIX_REND_MONO_DMX + if ( inputMc->base.inConfig == IVAS_REND_AUDIO_CONFIG_LS_CUSTOM ) + { + for ( i = 0; i < numInChannels; ++i ) + { + /* It's OK to also set gain 1 for LFE input channels here. + * Correct LFE handling will be applied within updateMcPanGains() */ + inputMc->panGains[i][0] = 1.f; + } + } + else + { + /* ls_conversion_cicpX_stereo contains gains for side speakers. + * These should be skipped with 5.1+X inputs. */ + skipSideSpeakers = false; + if ( inputMc->base.inConfig == IVAS_REND_AUDIO_CONFIG_5_1_2 || inputMc->base.inConfig == IVAS_REND_AUDIO_CONFIG_5_1_4 ) + { + skipSideSpeakers = true; + } + for ( readIdx = 0, writeIdx = 0; writeIdx < numInChannels; ++readIdx, ++writeIdx ) + { + if ( skipSideSpeakers && readIdx == 4 ) + { + /* Skip gains for side speakers in lookup table */ + readIdx += 2; + } + + inputMc->panGains[writeIdx][0] = ls_conversion_cicpX_mono[readIdx][0]; + } + } +#else for ( i = 0; i < numInChannels; ++i ) { /* It's OK to also set gain 1 for LFE input channels here. * Correct LFE handling will be applied within updateMcPanGains() */ inputMc->panGains[i][0] = 1.f; } +#endif return IVAS_ERR_OK; } @@ -1318,13 +1355,13 @@ static ivas_error updateMcPanGainsForMcOut( /* "if" conditions below realize the following mapping: If in == out, use identity matrix, otherwise follow the table: - +-----------+----------+---------------+-----------+--------------------+ - | in\out | MONO | STEREO | custom LS | other | - +-----------+----------+---------------+-----------+--------------------+ - | MONO | mono out | EFAP | EFAP | EFAP | - | custom LS | mono out | EFAP | EFAP | EFAP | - | other | mono out | stereo lookup | EFAP | conversion mapping | - +-----------+----------+---------------+-----------+--------------------+ + +-----------+-------------+---------------+-----------+--------------------+ + | in\out | MONO | STEREO | custom LS | other | + +-----------+-------------+---------------+-----------+--------------------+ + | MONO | mono out | EFAP | EFAP | EFAP | + | custom LS | mono out | EFAP | EFAP | EFAP | + | other | mono lookup | stereo lookup | EFAP | conversion mapping | + +-----------+-------------+---------------+-----------+--------------------+ */ if ( configsAreEqual( inputMc->base.inConfig, inputMc->customLsInput, outConfig, *inputMc->base.ctx.pCustomLsOut ) ) @@ -1514,6 +1551,12 @@ static ivas_error initMcBinauralRendering( { ivas_rend_closeCrend( &inputMc->crendWrapper ); } +#ifdef FIX_REND_ROT_MC_BIN + if ( inputMc->efapInWrapper.hEfap != NULL ) + { + efap_free_data( &inputMc->efapInWrapper.hEfap ); + } +#endif outSampleRate = *inputMc->base.ctx.pOutSampleRate; @@ -1557,6 +1600,14 @@ static ivas_error initMcBinauralRendering( } } +#ifdef FIX_REND_ROT_MC_BIN + /* Initialise the EFAP handle for rotation on input layout */ + if ( inConfig != IVAS_REND_AUDIO_CONFIG_LS_CUSTOM && inputMc->base.ctx.pHeadRotData->headRotEnabled ) + { + initEfap( &inputMc->efapInWrapper, inConfig, NULL ); + } +#endif + return error; } diff --git a/scripts/pyaudio3dtools/constants.py b/scripts/pyaudio3dtools/constants.py index b9523fc4ae28ff2eacb9a9c15ee409652f1cd2d9..92fd5a709e2ec7db67b8bdf7afbeff7cd2ebd56f 100644 --- a/scripts/pyaudio3dtools/constants.py +++ b/scripts/pyaudio3dtools/constants.py @@ -37,14 +37,14 @@ IVAS_CICPX_TO_MONO = np.array( 1, 1, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, + 0.79999995, + 0.79999995, + 0.79999995, + 0.79999995, + 0.849999964, + 0.849999964, + 0.849999964, + 0.849999964, ] ] ).T diff --git a/tests/renderer/constants.py b/tests/renderer/constants.py index da7302bdc2a4ab95bc507fd32eb32fcdfc49834e..b31557680628d5a95428458e4ac4c7e94bb92f0f 100644 --- a/tests/renderer/constants.py +++ b/tests/renderer/constants.py @@ -111,7 +111,7 @@ CREND_CMD = [ "-o", "/dev/null", # 6 -> output file # "-lp_lfe", - # "-limiter" + "-limiter" # "-no_delay_cmp" ] @@ -241,7 +241,9 @@ FORMAT_TO_CREND_FORMAT = { INPUT_FORMATS_AMBI = ["FOA", "HOA2", "HOA3"] INPUT_FORMATS_MC = ["MONO", "STEREO", "5_1", "5_1_2", "5_1_4", "7_1", "7_1_4"] INPUT_FORMATS_ISM = ["ISM1", "ISM2", "ISM3", "ISM4"] -INPUT_FORMATS_MASA = ["MASA2"] #["MASA1", "MASA2"] # Disable MASA1 tests until MASA1 can be implemented properly +INPUT_FORMATS_MASA = [ + "MASA2" +] # ["MASA1", "MASA2"] # Disable MASA1 tests until MASA1 can be implemented properly """ Non binaural / parametric output formats """ OUTPUT_FORMATS = [ @@ -381,36 +383,26 @@ pass_snr = { "test_ism[ISM4-HOA2]": 36, "test_ism[ISM4-HOA3]": 33, "test_ism[ISM4-STEREO]": 57, - # TODO delay alignment of LFE in binaural output # Failure reason: bitexact except for delay alignment of LFE signal (Issue 59) "test_multichannel_binaural_headrotation[5_1-BINAURAL-full_circle_in_15s]": 7, "test_multichannel_binaural_headrotation[5_1-BINAURAL-rotate_yaw_pitch_roll1]": 6, + "test_multichannel_binaural_headrotation[5_1_2-BINAURAL-full_circle_in_15s]": 9, + "test_multichannel_binaural_headrotation[5_1_2-BINAURAL-rotate_yaw_pitch_roll1]": 1, + "test_multichannel_binaural_headrotation[5_1_4-BINAURAL-full_circle_in_15s]": 10, + "test_multichannel_binaural_headrotation[5_1_4-BINAURAL-rotate_yaw_pitch_roll1]": 1, "test_multichannel_binaural_headrotation[7_1-BINAURAL-full_circle_in_15s]": 8, "test_multichannel_binaural_headrotation[7_1-BINAURAL-rotate_yaw_pitch_roll1]": 8, - # Failure reason: bitexact except for clicks and differences in center channel, could be due to crossfades - "test_multichannel_binaural_headrotation[5_1_2-BINAURAL-full_circle_in_15s]": 30, - "test_multichannel_binaural_headrotation[5_1_2-BINAURAL-rotate_yaw_pitch_roll1]": 30, - "test_multichannel_binaural_headrotation[5_1_4-BINAURAL-full_circle_in_15s]": 29, - "test_multichannel_binaural_headrotation[5_1_4-BINAURAL-rotate_yaw_pitch_roll1]": 29, - "test_multichannel_binaural_headrotation[7_1_4-BINAURAL-full_circle_in_15s]": 30, - "test_multichannel_binaural_headrotation[7_1_4-BINAURAL-rotate_yaw_pitch_roll1]": 30, - "test_multichannel_binaural_static[5_1_2-BINAURAL]": 30, - "test_multichannel_binaural_static[5_1_4-BINAURAL]": 29, - "test_multichannel_binaural_static[5_1-BINAURAL]": 27, - "test_multichannel_binaural_static[7_1-BINAURAL]": 30, - "test_multichannel_binaural_static[7_1_4-BINAURAL]": 30, - # TODO needs debugging - # Failure reason: headrotation may be applied differently, differences increase progressively - "test_multichannel_binaural_headrotation[5_1-BINAURAL_ROOM-full_circle_in_15s]": 10, - "test_multichannel_binaural_headrotation[5_1-BINAURAL_ROOM-rotate_yaw_pitch_roll1]": 4, - "test_multichannel_binaural_headrotation[5_1_2-BINAURAL_ROOM-full_circle_in_15s]": 11, - "test_multichannel_binaural_headrotation[5_1_2-BINAURAL_ROOM-rotate_yaw_pitch_roll1]": 3, - "test_multichannel_binaural_headrotation[5_1_4-BINAURAL_ROOM-full_circle_in_15s]": 12, - "test_multichannel_binaural_headrotation[5_1_4-BINAURAL_ROOM-rotate_yaw_pitch_roll1]": 3, - "test_multichannel_binaural_headrotation[7_1-BINAURAL_ROOM-full_circle_in_15s]": 10, - "test_multichannel_binaural_headrotation[7_1-BINAURAL_ROOM-rotate_yaw_pitch_roll1]": 3, - "test_multichannel_binaural_headrotation[7_1_4-BINAURAL_ROOM-full_circle_in_15s]": 10, - "test_multichannel_binaural_headrotation[7_1_4-BINAURAL_ROOM-rotate_yaw_pitch_roll1]": 3, + "test_multichannel_binaural_headrotation[7_1_4-BINAURAL-full_circle_in_15s]": 8, + "test_multichannel_binaural_headrotation[7_1_4-BINAURAL-rotate_yaw_pitch_roll1]": 1, + # Failure reason: differences in LFE alignment and possibly rotation + "test_multichannel_binaural_headrotation[5_1-BINAURAL_ROOM-full_circle_in_15s]": 14, + "test_multichannel_binaural_headrotation[5_1-BINAURAL_ROOM-rotate_yaw_pitch_roll1]": 12, + "test_multichannel_binaural_headrotation[5_1_2-BINAURAL_ROOM-full_circle_in_15s]": 8, + "test_multichannel_binaural_headrotation[5_1_4-BINAURAL_ROOM-full_circle_in_15s]": 6, + "test_multichannel_binaural_headrotation[5_1_4-BINAURAL_ROOM-rotate_yaw_pitch_roll1]": 6, + "test_multichannel_binaural_headrotation[7_1-BINAURAL_ROOM-full_circle_in_15s]": 11, + "test_multichannel_binaural_headrotation[7_1-BINAURAL_ROOM-rotate_yaw_pitch_roll1]": 9, + "test_multichannel_binaural_headrotation[5_1_2-BINAURAL_ROOM-rotate_yaw_pitch_roll1]": 6, ##################################### # # External vs Internal Renderer tests @@ -485,38 +477,36 @@ pass_snr = { "test_multichannel_binaural_headrotation_vs_decoder[5_1_4-BINAURAL-rotate_yaw_pitch_roll1]": 0, "test_multichannel_binaural_headrotation_vs_decoder[7_1_4-BINAURAL-full_circle_in_15s]": 4, "test_multichannel_binaural_headrotation_vs_decoder[7_1_4-BINAURAL-rotate_yaw_pitch_roll1]": 0, - # TODO needs investigation - "test_multichannel_binaural_headrotation_vs_decoder[5_1-BINAURAL_ROOM-full_circle_in_15s]": 5, - "test_multichannel_binaural_headrotation_vs_decoder[5_1-BINAURAL_ROOM-rotate_yaw_pitch_roll1]": 0, - "test_multichannel_binaural_headrotation_vs_decoder[5_1_2-BINAURAL_ROOM-full_circle_in_15s]": 6, - "test_multichannel_binaural_headrotation_vs_decoder[5_1_2-BINAURAL_ROOM-rotate_yaw_pitch_roll1]": 0, - "test_multichannel_binaural_headrotation_vs_decoder[5_1_4-BINAURAL_ROOM-full_circle_in_15s]": 7, - "test_multichannel_binaural_headrotation_vs_decoder[5_1_4-BINAURAL_ROOM-rotate_yaw_pitch_roll1]": 0, - "test_multichannel_binaural_headrotation_vs_decoder[7_1-BINAURAL_ROOM-full_circle_in_15s]": 5, - "test_multichannel_binaural_headrotation_vs_decoder[7_1-BINAURAL_ROOM-rotate_yaw_pitch_roll1]": 0, - "test_multichannel_binaural_headrotation_vs_decoder[7_1_4-BINAURAL_ROOM-full_circle_in_15s]": 5, - "test_multichannel_binaural_headrotation_vs_decoder[7_1_4-BINAURAL_ROOM-rotate_yaw_pitch_roll1]": 0, - # TODO needs investigation + # # TODO needs investigation + "test_multichannel_binaural_headrotation_vs_decoder[5_1-BINAURAL_ROOM-full_circle_in_15s]": 7, + "test_multichannel_binaural_headrotation_vs_decoder[5_1-BINAURAL_ROOM-rotate_yaw_pitch_roll1]": 6, + "test_multichannel_binaural_headrotation_vs_decoder[5_1_2-BINAURAL_ROOM-full_circle_in_15s]": 3, + "test_multichannel_binaural_headrotation_vs_decoder[5_1_2-BINAURAL_ROOM-rotate_yaw_pitch_roll1]": 2, + "test_multichannel_binaural_headrotation_vs_decoder[5_1_4-BINAURAL_ROOM-full_circle_in_15s]": 2, + "test_multichannel_binaural_headrotation_vs_decoder[5_1_4-BINAURAL_ROOM-rotate_yaw_pitch_roll1]": 2, + "test_multichannel_binaural_headrotation_vs_decoder[7_1-BINAURAL_ROOM-full_circle_in_15s]": 7, + "test_multichannel_binaural_headrotation_vs_decoder[7_1-BINAURAL_ROOM-rotate_yaw_pitch_roll1]": 5, + "test_multichannel_binaural_headrotation_vs_decoder[7_1_4-BINAURAL_ROOM-full_circle_in_15s]": 16, + "test_multichannel_binaural_headrotation_vs_decoder[7_1_4-BINAURAL_ROOM-rotate_yaw_pitch_roll1]": 16, + # Failure reason: Differences seem to be purely in late reverb part "test_multichannel_binaural_static_vs_decoder[5_1_2-BINAURAL_ROOM]": 18, "test_multichannel_binaural_static_vs_decoder[5_1_4-BINAURAL_ROOM]": 18, "test_multichannel_binaural_static_vs_decoder[5_1-BINAURAL_ROOM]": 18, "test_multichannel_binaural_static_vs_decoder[7_1_4-BINAURAL_ROOM]": 18, "test_multichannel_binaural_static_vs_decoder[7_1-BINAURAL_ROOM]": 19, - # Failure reason: Mono downmix significantly different, needs a fix + # Failure reason: R channel in MONO output is delayed "test_multichannel_vs_decoder[5_1_2-MONO]": 1, "test_multichannel_vs_decoder[5_1_4-MONO]": 1, "test_multichannel_vs_decoder[5_1-MONO]": 1, "test_multichannel_vs_decoder[7_1_4-MONO]": 1, "test_multichannel_vs_decoder[7_1-MONO]": 1, "test_multichannel_vs_decoder[STEREO-MONO]": 17, - # Failure reason: Stereo downmix differs slightly, needs a fix + # Failure reason: Active dmx (decoder) vs Passive dmx (renderer) "test_multichannel_vs_decoder[5_1_2-STEREO]": 44, "test_multichannel_vs_decoder[5_1_4-STEREO]": 48, "test_multichannel_vs_decoder[5_1-STEREO]": 48, "test_multichannel_vs_decoder[7_1_4-STEREO]": 46, "test_multichannel_vs_decoder[7_1-STEREO]": 44, - # TODO needs investigation - # Failure reason: possibly due to minor differences in crossfades "test_multichannel_vs_decoder[5_1_2-5_1_4]": 63, "test_multichannel_vs_decoder[5_1_2-5_1]": 63, "test_multichannel_vs_decoder[5_1_2-7_1_4]": 63, diff --git a/tests/renderer/utils.py b/tests/renderer/utils.py index 8a4ecf739b67d5f199ec54f296cfbff1e7b019eb..b22cdc9f6978ad23cc0752d00a0ed48943fde570 100644 --- a/tests/renderer/utils.py +++ b/tests/renderer/utils.py @@ -177,7 +177,6 @@ def run_renderer( out_file = str(output_path_base.joinpath(f"{in_name}_to_{out_name}{trj_name}.wav")) - cmd = RENDERER_CMD[:] cmd[2] = str(in_file) cmd[4] = str(in_fmt) @@ -389,7 +388,11 @@ def run_pyscripts( def compare_renderer_vs_mergetarget(test_info, in_fmt, out_fmt, **kwargs): ref, ref_fs = run_renderer( - in_fmt, out_fmt, binary_suffix=BIN_SUFFIX_MERGETARGET, output_path_base=OUTPUT_PATH_REF, **kwargs + in_fmt, + out_fmt, + binary_suffix=BIN_SUFFIX_MERGETARGET, + output_path_base=OUTPUT_PATH_REF, + **kwargs, ) cut, cut_fs = run_renderer(in_fmt, out_fmt, **kwargs) check_BE(test_info, ref, ref_fs, cut, cut_fs) @@ -414,12 +417,18 @@ def compare_renderer_vs_td_standalone(test_info, in_fmt, out_fmt, **kwargs): def compare_renderer_vs_decoder(test_info, in_fmt, out_fmt, **kwargs): + if "trj_file" in kwargs: + trj_name = f"_{kwargs['trj_file'].stem}" + else: + trj_name = "" with TemporaryDirectory() as tmp_dir: tmp_dir = Path(tmp_dir) in_meta_files = None - bit_file = str(tmp_dir.joinpath(f"{in_fmt}_to_{out_fmt}.192")) - out_file_decoder = str(OUTPUT_PATH_REF.joinpath(f"{in_fmt}_to_{out_fmt}.wav")) + bit_file = str(tmp_dir.joinpath(f"{in_fmt}_to_{out_fmt}{trj_name}.192")) + out_file_decoder = str( + OUTPUT_PATH_REF.joinpath(f"{in_fmt}_to_{out_fmt}{trj_name}.wav") + ) # Ref: cod -> dec (out_fmt) if in_fmt in FORMAT_TO_METADATA_FILES.keys(): @@ -440,7 +449,7 @@ def compare_renderer_vs_decoder(test_info, in_fmt, out_fmt, **kwargs): else: tmp_fmt = in_fmt - out_file_ext = str(tmp_dir.joinpath(f"{in_fmt}_to_{tmp_fmt}.wav")) + out_file_ext = str(tmp_dir.joinpath(f"{in_fmt}_to_{tmp_fmt}{trj_name}.wav")) # passthrough decoder run_dec(bit_file, out_file_ext, tmp_fmt, **kwargs)