diff --git a/lib_com/options.h b/lib_com/options.h index fc3d5173a82f8f79fefbdca257ef0af5236f60b2..de58cbabd78771d230e958b9b2ed6e026086fb9d 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -161,6 +161,7 @@ /*#define FIX_I4_OL_PITCH*/ /* fix open-loop pitch used for EVS core switching */ #define TMP_1342_WORKAROUND_DEC_FLUSH_BROKEN_IN_SR /* FhG: Temporary workaround for incorrect implementation of decoder flush with split rendering */ +#define FIX_1466_EXTREND /* FhG: issue 1466: enable rendering of mono/stereo to other formats in the external renderer */ #define NONBE_1122_KEEP_EVS_MODE_UNCHANGED /* FhG: Disables fix for issue 1122 in EVS mode to keep BE tests green. This switch should be removed once the 1122 fix is added to EVS via a CR. */ #define FIX_CLANG18_MSAN_IN_DEC_INIT_BY_MOVING_COMMON_INITS_TOGETHER /* FhG: fix CLANG18 MSAN error in decoder init */ #define FIX_1481_CLANG18_MSAN_INIT_LAST_ELEM_BRATE /* FhG: initialize last_element_brate to avoid CLANG18 MSAN complaint */ diff --git a/lib_dec/ivas_output_config.c b/lib_dec/ivas_output_config.c index 14a56f8adf32dcb400dea893f7e5a930888d936c..09fa8052f196929f89a76b8e64ef35b03beb875d 100644 --- a/lib_dec/ivas_output_config.c +++ b/lib_dec/ivas_output_config.c @@ -228,9 +228,17 @@ void ivas_renderer_select( * Non-binaural rendering configurations *-----------------------------------------------------------------*/ +#ifdef FIX_1435_MOVE_STEREO_PANNING + else if ( st_ivas->ivas_format == MONO_FORMAT || st_ivas->ivas_format == STEREO_FORMAT ) +#else else if ( st_ivas->ivas_format == MONO_FORMAT ) +#endif { +#ifdef FIX_1435_MOVE_STEREO_PANNING + if ( st_ivas->ivas_format == MONO_FORMAT && output_config == IVAS_AUDIO_CONFIG_STEREO ) +#else if ( output_config == IVAS_AUDIO_CONFIG_STEREO ) +#endif { *renderer_type = RENDERER_NON_DIEGETIC_DOWNMIX; } @@ -238,6 +246,13 @@ void ivas_renderer_select( { *renderer_type = RENDERER_MC; } +#ifdef FIX_1435_MOVE_STEREO_PANNING + else if ( st_ivas->ivas_format == STEREO_FORMAT && + ( output_config == IVAS_AUDIO_CONFIG_FOA || output_config == IVAS_AUDIO_CONFIG_HOA2 || output_config == IVAS_AUDIO_CONFIG_HOA3 ) ) + { + *renderer_type = RENDERER_SBA_LINEAR_ENC; + } +#endif } else if ( st_ivas->ivas_format == ISM_FORMAT ) { diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 9462886b3f5cb2f9ef8b63108d43f4eb17cdf841..ac8abba9355d8be2f395ae1478f408e263505a63 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -1262,11 +1262,26 @@ static bool isIoConfigPairSupported( const AUDIO_CONFIG inConfig, const AUDIO_CONFIG outConfig ) { +#ifdef FIX_1466_EXTREND + /* input config cannot be binaural */ + if ( ( getAudioConfigType( inConfig ) == IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL ) && + ( inConfig != IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED && inConfig != IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) + { + return false; + } + + /* output config cannot be object based */ + if ( getAudioConfigType( outConfig ) == IVAS_REND_AUDIO_CONFIG_TYPE_OBJECT_BASED ) + { + return false; + } +#else /* Rendering mono or stereo to binaural is not supported */ if ( ( inConfig == IVAS_AUDIO_CONFIG_MONO || inConfig == IVAS_AUDIO_CONFIG_STEREO ) && getAudioConfigType( outConfig ) == IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL ) { return false; } +#endif /* If not returned so far, config pair is supported */ return true; @@ -2208,15 +2223,47 @@ static ivas_error updateMcPanGainsForAmbiOut( { int16_t ch_in, ch_out, lfeIdx; int16_t numNonLfeInChannels, outAmbiOrder; +#ifdef FIX_1466_EXTREND + AUDIO_CONFIG inConfig; +#endif const float *spkAzi, *spkEle; ivas_error error; +#ifdef FIX_1466_EXTREND + inConfig = inputMc->base.inConfig; + +#endif if ( ( error = getAmbisonicsOrder( outConfig, &outAmbiOrder ) ) != IVAS_ERR_OK ) { return error; } +#ifdef FIX_1466_EXTREND + if ( inConfig == IVAS_AUDIO_CONFIG_MONO || + inConfig == IVAS_AUDIO_CONFIG_STEREO ) + { + setZeroPanMatrix( inputMc->panGains ); + if ( inConfig == IVAS_AUDIO_CONFIG_MONO ) + { + /* W = Mono */ + inputMc->panGains[0][0] = 1.f; + } + else + { + /* W = 0.5 * ( L + R ) */ + inputMc->panGains[0][0] = 0.5f; + inputMc->panGains[0][1] = 0.5f; + /* Y = 0.5 * ( L - R ) */ + inputMc->panGains[1][0] = 0.5f; + inputMc->panGains[1][1] = -0.5f; + } + + return IVAS_ERR_OK; + } + else if ( inConfig != IVAS_AUDIO_CONFIG_LS_CUSTOM ) +#else if ( inputMc->base.inConfig != IVAS_AUDIO_CONFIG_LS_CUSTOM ) +#endif { if ( ( error = getNumNonLfeChannelsInSpeakerLayout( inputMc->base.inConfig, &numNonLfeInChannels ) ) != IVAS_ERR_OK ) { @@ -2272,6 +2319,26 @@ static ivas_error updateMcPanGainsForAmbiOut( return IVAS_ERR_OK; } +#ifdef FIX_1466_EXTREND +static ivas_error updateMcPanGainsForBinauralOut( + input_mc *inputMc ) +{ + setZeroPanMatrix( inputMc->panGains ); + if ( inputMc->base.inConfig == IVAS_AUDIO_CONFIG_MONO ) + { + inputMc->panGains[0][0] = ( inputMc->nonDiegeticPanGain + 1.f ) * 0.5f; + inputMc->panGains[0][1] = 1.f - inputMc->panGains[0][0]; + } + else + { + /* stereo passthrough */ + inputMc->panGains[0][0] = 1.f; + inputMc->panGains[1][1] = 1.f; + } + + return IVAS_ERR_OK; +} +#endif static ivas_error updateMcPanGains( input_mc *inputMc, @@ -2293,6 +2360,15 @@ static ivas_error updateMcPanGains( error = updateMcPanGainsForAmbiOut( inputMc, outConfig ); break; case IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL: +#ifdef FIX_1466_EXTREND + if ( inputMc->base.inConfig == IVAS_AUDIO_CONFIG_MONO || inputMc->base.inConfig == IVAS_AUDIO_CONFIG_STEREO ) + { + error = updateMcPanGainsForBinauralOut( inputMc ); + break; + } + + /* not mono or stereo */ +#endif switch ( outConfig ) { case IVAS_AUDIO_CONFIG_BINAURAL: @@ -2351,6 +2427,13 @@ static ivas_error initMcBinauralRendering( int32_t binauralDelayNs; int32_t outSampleRate; int8_t useTDRend; +#ifdef FIX_1466_EXTREND + + if ( inputMc->base.inConfig == IVAS_AUDIO_CONFIG_MONO || inputMc->base.inConfig == IVAS_AUDIO_CONFIG_STEREO ) + { + return IVAS_ERR_OK; + } +#endif /* Allocate TD binaural renderer for custom loudspeaker layouts (regardless of headrotation) or planar MC layouts with headrotation, CREND for the rest */ @@ -6246,6 +6329,27 @@ static ivas_error renderActiveInputsIsm( return IVAS_ERR_OK; } +#ifdef FIX_1466_EXTREND +static void renderMonoStereoToBinaural( + const input_mc *mcInput, + IVAS_REND_AudioBuffer outAudio ) +{ + int16_t i; + IVAS_REND_AudioBuffer inAudio; + + push_wmops( "renderMonoStereoToBinaural" ); + inAudio = mcInput->base.inputBuffer; + + for ( i = 0; i < inAudio.config.numChannels; ++i ) + { + renderBufferChannel( inAudio, i, mcInput->panGains[i], outAudio ); + } + + pop_wmops(); + + return; +} +#endif static ivas_error renderLfeToBinaural( const input_mc *mcInput, @@ -6846,6 +6950,15 @@ static ivas_error renderInputMc( renderMcToSba( mcInput, outAudio ); break; case IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL: +#ifdef FIX_1466_EXTREND + if ( mcInput->base.inConfig == IVAS_AUDIO_CONFIG_MONO || mcInput->base.inConfig == IVAS_AUDIO_CONFIG_STEREO ) + { + renderMonoStereoToBinaural( mcInput, outAudio ); + break; + } + + /* not mono or stereo */ +#endif switch ( outConfig ) { case IVAS_AUDIO_CONFIG_BINAURAL: diff --git a/scripts/config/ivas_modes.json b/scripts/config/ivas_modes.json index 72941df4593e4ed56c1ddb745218a483eb73df9f..ff4728ec66651e1dd69f51c470a8fd27ec55e166 100644 --- a/scripts/config/ivas_modes.json +++ b/scripts/config/ivas_modes.json @@ -61,6 +61,70 @@ ] } }, + "mono_upmix_b{bitrate}_{bandwidth}_cbr": { + "encmodeoption": [], + "encoptions": [ + "-max_band", + "{bandwidth}" + ], + "dec": { + "STEREO": [], + "5_1": [], + "5_1_2": [], + "5_1_4": [], + "7_1": [], + "7_1_4": [], + "BINAURAL": [], + "BINAURAL_ROOM_IR": [], + "BINAURAL_ROOM_REVERB": [], + "EXT": [], + "FOA": [], + "HOA2": [], + "HOA3": [] + }, + "in_config": "MONO", + "table_name": "Mono Upmix@{table_bitrate} kbps {bandwidth}", + "nummetadata": 0, + "metadatafilenames": [], + "rs": false, + "amr": false, + "mono": true, + "bitrates": { + "wb": [ + 7200, + 8000, + 9600, + 13200, + 16400, + 24400, + 32000, + 48000, + 64000, + 96000, + 128000 + ], + "swb": [ + 9600, + 13200, + 16400, + 24400, + 32000, + 48000, + 64000, + 96000, + 128000 + ], + "fb": [ + 16400, + 24400, + 32000, + 48000, + 64000, + 96000, + 128000 + ] + } + }, "mono_b{bitrate}_{bandwidth}_rf_lo2_cbr": { "encmodeoption": [], "encoptions": [ @@ -4334,7 +4398,13 @@ "5_1": [], "mono": [], "stereo": [], - "EXT": [] + "EXT": [], + "BINAURAL": [], + "BINAURAL_ROOM_IR": [], + "BINAURAL_ROOM_REVERB": [], + "FOA": [], + "HOA2": [], + "HOA3": [] }, "in_config": "STEREO", "table_name": "Stereo@{table_bitrate} kbps {bandwidth}", diff --git a/scripts/pyivastest/IvasModeRunner.py b/scripts/pyivastest/IvasModeRunner.py index 1251f105864d60acc28cad7fb993ec95d96adefc..1aa44078fded51acf02d18bc0cf8e7623c64ad12 100644 --- a/scripts/pyivastest/IvasModeRunner.py +++ b/scripts/pyivastest/IvasModeRunner.py @@ -245,7 +245,10 @@ class IvasModeRunner(IvasModeCollector.IvasModeCollector): with self.lock: if self.stats: if not self.run_encoder: - if config["config"]["num_dec_remaining"] == config["config"]["num_dec"]: + if ( + config["config"]["num_dec_remaining"] + == config["config"]["num_dec"] + ): self.stats["num_modes_running"] += 1 self.stats["num_decs_running"] += 1 config["config"]["num_dec_remaining"] -= 1 @@ -297,15 +300,25 @@ class IvasModeRunner(IvasModeCollector.IvasModeCollector): self.logger.error("Exception in ivas_dec_thread(): " + str(e)) return - if not config["mono"]: + if config["mono"] and output_config.lower() != "mono": + dec_options.extend(["-evs"]) + dec_options.extend([output_config]) + elif not config["mono"]: dec_options.extend([output_config]) + dec_options = [ - x.format(dec_file_name=dec_file_name) if "{dec_file_name}" in x else x + ( + x.format(dec_file_name=dec_file_name) + if "{dec_file_name}" in x + else x + ) for x in dec_options if x != [] ] enc_file_name = config["enc_file_name"] - self.logger.info("Decoding {} to {}".format(enc_file_name, dec_file_name)) + self.logger.info( + "Decoding {} to {}".format(enc_file_name, dec_file_name) + ) if self.test_tool != "": dec_cmd = ( self.test_tool @@ -453,7 +466,9 @@ class IvasModeRunner(IvasModeCollector.IvasModeCollector): if isinstance(in_file_name, list): metadata_file_names = in_file_name[1:] in_file_name = in_file_name[0] - self.logger.info("Encoding Mode {} input file {}".format(mode, in_file_name)) + self.logger.info( + "Encoding Mode {} input file {}".format(mode, in_file_name) + ) with self.lock: if self.stats: @@ -538,12 +553,8 @@ class IvasModeRunner(IvasModeCollector.IvasModeCollector): ) ) - pcm_log_name_tmp = "".join( - [pcm_base_name, constants.LOG_FILE_EXT] - ) - pcm_log_name = os.path.join( - self.dir_name, "logs", pcm_log_name_tmp - ) + pcm_log_name_tmp = "".join([pcm_base_name, constants.LOG_FILE_EXT]) + pcm_log_name = os.path.join(self.dir_name, "logs", pcm_log_name_tmp) with open(pcm_log_name, "w") as pcm_log: pcm_name_res_tmp = pcm_name + ".res.wav" @@ -594,8 +605,8 @@ class IvasModeRunner(IvasModeCollector.IvasModeCollector): cut_len_samples = end_time_samples - start_time_samples if ( - cut_len_samples + start_time_samples < in_len - or start_time_samples > 0 + cut_len_samples + start_time_samples < in_len + or start_time_samples > 0 ): end_time_samples = min(end_time_samples, in_len) sig = ar.cut( @@ -767,7 +778,9 @@ class IvasModeRunner(IvasModeCollector.IvasModeCollector): if error == 0 and "bitstream_processing" in enc_dec_cmd: bs_in_file = enc_file_name - proc_chain = deepcopy(enc_dec_cmd["bitstream_processing"]["proc_chain"]) + proc_chain = deepcopy( + enc_dec_cmd["bitstream_processing"]["proc_chain"] + ) for processing in proc_chain: suffix = processing.pop() bs_out_file = ".".join( @@ -823,7 +836,9 @@ class IvasModeRunner(IvasModeCollector.IvasModeCollector): os.remove(pcm_name) self.logger.console( - "Exception when encoding item {}: {}".format(enc_file_name, str(exc)), + "Exception when encoding item {}: {}".format( + enc_file_name, str(exc) + ), logging.ERROR, ) self.logger.console( @@ -841,7 +856,10 @@ class IvasModeRunner(IvasModeCollector.IvasModeCollector): if not self.run_decoder: self.stats["num_modes_running"] -= 1 self.stats["num_modes_finished"] -= 1 - if self.enc_queue["num_modes_enc"] == self.enc_queue["num_modes_enc_done"]: + if ( + self.enc_queue["num_modes_enc"] + == self.enc_queue["num_modes_enc_done"] + ): self.dec_queue["all_encoded"] = True self.stats["num_encs_finished"] += 1 self.stats["num_encs_running"] -= 1 @@ -1206,7 +1224,9 @@ class IvasModeRunner(IvasModeCollector.IvasModeCollector): ] enc_log.write(" ".join(proc_cmd)) - proc_result = subprocess.run(proc_cmd, capture_output=True, text=True) + proc_result = subprocess.run( + proc_cmd, capture_output=True, text=True + ) enc_log.write(proc_result.stderr) enc_log.write(proc_result.stdout) error = proc_result.returncode @@ -1224,7 +1244,9 @@ class IvasModeRunner(IvasModeCollector.IvasModeCollector): bs_in_file = bs_out_file except Exception as exc: self.logger.error( - "Exception processing bitstream {}: {}".format(enc_file_name, str(exc)) + "Exception processing bitstream {}: {}".format( + enc_file_name, str(exc) + ) ) self.logger.error("failed command: {}".format(" ".join(proc_cmd))) self.logger.error(