diff --git a/apps/decoder.c b/apps/decoder.c index ed96f7919618ff1fc2c47531da14f77b5b81b8de..4feea3fcfd1d70e937c9f610c2bede86748b809c 100644 --- a/apps/decoder.c +++ b/apps/decoder.c @@ -150,6 +150,9 @@ typedef struct uint16_t directivityPatternId[IVAS_MAX_NUM_OBJECTS]; bool objEditEnabled; char *objEditFileName; +#ifdef FIX_1419_MONO_STEREO_UMX + bool evsMode; +#endif } DecArguments; @@ -961,6 +964,9 @@ static bool parseCmdlIVAS_dec( arg->output_Fs = IVAS_MAX_SAMPLING_RATE; arg->outputConfig = IVAS_AUDIO_CONFIG_MONO; arg->decMode = IVAS_DEC_MODE_IVAS; +#ifdef FIX_1419_MONO_STEREO_UMX + arg->evsMode = false; +#endif arg->quietModeEnabled = false; arg->delayCompensationEnabled = true; arg->voipMode = false; @@ -1502,6 +1508,14 @@ static bool parseCmdlIVAS_dec( } i++; } +#ifdef FIX_1419_MONO_STEREO_UMX + else if ( strcmp( argv_to_upper, "-EVS" ) == 0 ) + { + arg->evsMode = true; + arg->decMode = IVAS_DEC_MODE_EVS; + i++; + } +#endif /*-----------------------------------------------------------------* * Option not recognized @@ -1644,6 +1658,9 @@ static bool parseCmdlIVAS_dec( static void usage_dec( void ) { fprintf( stdout, "Usage for EVS: IVAS_dec.exe [Options] Fs bitstream_file output_file\n" ); +#ifdef FIX_1419_MONO_STEREO_UMX + fprintf( stdout, " OR usage for IVAS (below) with -evs option and OutputConf\n" ); +#endif fprintf( stdout, "Usage for IVAS: IVAS_dec.exe [Options] OutputConf Fs bitstream_file output_file\n\n" ); fprintf( stdout, "Mandatory parameters:\n" ); @@ -1660,6 +1677,9 @@ static void usage_dec( void ) fprintf( stdout, "Options:\n" ); fprintf( stdout, "--------\n" ); +#ifdef FIX_1419_MONO_STEREO_UMX + fprintf( stdout, "-evs : Specify EVS mode for supplied bitstream\n" ); +#endif fprintf( stdout, "-VOIP : VoIP mode: RTP in G192\n" ); fprintf( stdout, "-VOIP_hf_only=0 : VoIP mode: EVS RTP Payload Format hf_only=0 in rtpdump\n" ); #ifdef IVAS_RTPDUMP diff --git a/lib_com/common_api_types.h b/lib_com/common_api_types.h index 80c90d6b3152a5ace3ef0f0f205ac0c61784a356..18a0aea9f631b3d3a35f489eedbdfc68e66a233b 100644 --- a/lib_com/common_api_types.h +++ b/lib_com/common_api_types.h @@ -222,6 +222,18 @@ typedef enum _ivas_binaural_renderer_type IVAS_BIN_RENDERER_TYPE_DEFAULT, } IVAS_BIN_RENDERER_TYPE; +#ifdef FIX_1419_MONO_STEREO_UMX + +typedef struct _IVAS_MS_UMX_CONF_DATA +{ + int16_t spatialEnabled; /* internal flag for spatial rendering */ + int16_t stereoLR; /* internal flag to use ±90 for BRIRs */ + float radius; + float azi[2]; + float ele[2]; + +} IVAS_MS_UMX_CONF_DATA, *IVAS_MS_UMX_CONF_HANDLE; +#endif /*----------------------------------------------------------------------------------* * Split rendering API constants, structures, and enums @@ -335,6 +347,9 @@ typedef struct _IVAS_RENDER_CONFIG #endif IVAS_ROOM_ACOUSTICS_CONFIG_DATA roomAcoustics; ISAR_SPLIT_REND_CONFIG_DATA split_rend_config; +#ifdef FIX_1419_MONO_STEREO_UMX + IVAS_MS_UMX_CONF_DATA mono_stereo_upmix_config; +#endif float directivity[IVAS_MAX_NUM_OBJECTS * 3]; float distAtt[3]; diff --git a/lib_com/ivas_cnst.h b/lib_com/ivas_cnst.h index 3e8521f47d8f5fc485771b6c1ce76bfaffcf783d..c169b7684ad9688c7624a8bbd49a97a637221bb9 100755 --- a/lib_com/ivas_cnst.h +++ b/lib_com/ivas_cnst.h @@ -1251,7 +1251,11 @@ typedef enum *----------------------------------------------------------------------------------*/ #define MC_LS_SETUP_BITS 3 /* number of bits for writing the MC LS configuration */ +#ifdef FIX_1419_MONO_STEREO_UMX +#define LS_SETUP_CONVERSION_NUM_MAPPINGS 41 /* number of mappings for LS setup conversion */ +#else #define LS_SETUP_CONVERSION_NUM_MAPPINGS 35 /* number of mappings for LS setup conversion */ +#endif typedef enum { diff --git a/lib_com/options.h b/lib_com/options.h index b72be74b4f342769a8b21a0bde86c3029b833403..124f59632fddfae8e6253ffed72a5a9b13c825ea 100755 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -170,6 +170,7 @@ #define TMP_1342_WORKAROUND_DEC_FLUSH_BROKEN_IN_SR /* FhG: Temporary workaround for incorrect implementation of decoder flush with split rendering */ #define FIX_1413_IGF_INIT_PRINTOUT /* FhG: use correct variable for IGF initiliazation */ #define RENDERER_MD_SYNC_DELAY_TO_INTEGER /* FhG: change data type of metadata sync delay in ext renderer to int16_t for better BASOP portability (and nicer code) */ +#define FIX_1419_MONO_STEREO_UMX /* FhG: fix for issue 1418 : support upmix to all output formats for mono and stereo */ /* #################### End BE switches ################################## */ diff --git a/lib_dec/ivas_init_dec.c b/lib_dec/ivas_init_dec.c index 80b8c7e5e961c7713b4de1e009490e5fe82e7b40..7b4f178239963236a198721981b721443b79cbb0 100644 --- a/lib_dec/ivas_init_dec.c +++ b/lib_dec/ivas_init_dec.c @@ -1279,7 +1279,15 @@ ivas_error ivas_init_decoder( if ( output_config == IVAS_AUDIO_CONFIG_EXTERNAL ) { +#ifdef FIX_1419_MONO_STEREO_UMX + if ( st_ivas->ivas_format == MONO_FORMAT ) + { + hDecoderConfig->nchan_out = 1; + } + else if ( st_ivas->ivas_format == STEREO_FORMAT ) +#else if ( st_ivas->ivas_format == STEREO_FORMAT ) +#endif { hDecoderConfig->nchan_out = CPE_CHANNELS; } @@ -1332,12 +1340,30 @@ ivas_error ivas_init_decoder( st_ivas->hOutSetup.output_config = st_ivas->intern_config; st_ivas->hOutSetup.nchan_out_woLFE = audioCfg2channels( st_ivas->intern_config ); } +#ifdef FIX_1419_MONO_STEREO_UMX + + if ( st_ivas->ivas_format == MONO_FORMAT || st_ivas->ivas_format == STEREO_FORMAT ) + { + st_ivas->transport_config = ( st_ivas->ivas_format == MONO_FORMAT ) ? IVAS_AUDIO_CONFIG_MONO : IVAS_AUDIO_CONFIG_STEREO; + } +#endif /* Only initialize transport setup if it is used */ if ( st_ivas->transport_config != IVAS_AUDIO_CONFIG_INVALID ) { ivas_output_init( &( st_ivas->hTransSetup ), st_ivas->transport_config ); } +#ifdef FIX_1419_MONO_STEREO_UMX + + /* Override transport config values from render config */ + if ( ( st_ivas->ivas_format == MONO_FORMAT || st_ivas->ivas_format == STEREO_FORMAT ) && + st_ivas->hRenderConfig != NULL && + st_ivas->hRenderConfig->mono_stereo_upmix_config.spatialEnabled ) + { + st_ivas->hTransSetup.ls_azimuth = st_ivas->hRenderConfig->mono_stereo_upmix_config.azi; + st_ivas->hTransSetup.ls_elevation = st_ivas->hRenderConfig->mono_stereo_upmix_config.ele; + } +#endif if ( st_ivas->ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCMASA ) { @@ -1414,7 +1440,9 @@ ivas_error ivas_init_decoder( else if ( st_ivas->ivas_format == STEREO_FORMAT ) { st_ivas->nchan_transport = CPE_CHANNELS; +#ifndef FIX_1419_MONO_STEREO_UMX /* already set now by renderer_select() */ st_ivas->intern_config = IVAS_AUDIO_CONFIG_STEREO; +#endif st_ivas->nSCE = 0; st_ivas->nCPE = 1; /* in stereo, there is always only one CPE */ @@ -2148,7 +2176,13 @@ ivas_error ivas_init_decoder( } else if ( st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV || st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV_ROOM ) { +#ifdef FIX_1419_MONO_STEREO_UMX + if ( ( st_ivas->hDecoderConfig->Opt_Headrotation || st_ivas->hDecoderConfig->Opt_ExternalOrientation ) && + ( ( st_ivas->ivas_format == MONO_FORMAT || st_ivas->ivas_format == STEREO_FORMAT ) || + ( st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV_ROOM && st_ivas->ivas_format == MC_FORMAT ) ) ) +#else if ( st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV_ROOM && st_ivas->ivas_format == MC_FORMAT && ( st_ivas->hDecoderConfig->Opt_Headrotation || st_ivas->hDecoderConfig->Opt_ExternalOrientation ) ) +#endif { if ( ( error = efap_init_data( &( st_ivas->hEFAPdata ), st_ivas->hIntSetup.ls_azimuth, st_ivas->hIntSetup.ls_elevation, st_ivas->hIntSetup.nchan_out_woLFE, EFAP_MODE_EFAP ) ) != IVAS_ERR_OK ) { @@ -2304,7 +2338,8 @@ ivas_error ivas_init_decoder( } /*-----------------------------------------------------------------* - * LFE handles for rendering after rendering to adjust LFE delay to filter delay + * LFE handles for rendering after rendering to adjust LFE delay to + * filter delay *-----------------------------------------------------------------*/ if ( st_ivas->mc_mode == MC_MODE_MCT || st_ivas->mc_mode == MC_MODE_PARAMUPMIX ) @@ -3136,6 +3171,7 @@ static ivas_error doSanityChecks_IVAS( return IVAS_ERROR( IVAS_ERR_INVALID_OUTPUT_FORMAT, "Error: Non-diegetic panning not supported in this IVAS format" ); } +#ifndef FIX_1419_MONO_STEREO_UMX /* we now support basically everything for stereo */ /* Verify stereo output configuration */ if ( st_ivas->ivas_format == STEREO_FORMAT ) { @@ -3148,10 +3184,21 @@ static ivas_error doSanityChecks_IVAS( else { if ( output_config == IVAS_AUDIO_CONFIG_INVALID ) +#else /* exclude invalid configs instead of matching valid ones */ + if ( output_config == IVAS_AUDIO_CONFIG_INVALID || + output_config == IVAS_AUDIO_CONFIG_ISM1 || + output_config == IVAS_AUDIO_CONFIG_ISM2 || + output_config == IVAS_AUDIO_CONFIG_ISM3 || + output_config == IVAS_AUDIO_CONFIG_ISM4 || + output_config == IVAS_AUDIO_CONFIG_MASA1 || + output_config == IVAS_AUDIO_CONFIG_MASA2 ) +#endif { return IVAS_ERROR( IVAS_ERR_INVALID_OUTPUT_FORMAT, "Incorrect output configuration specified!" ); } +#ifndef FIX_1419_MONO_STEREO_UMX } +#endif if ( ( output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) && output_Fs != 48000 ) { diff --git a/lib_dec/ivas_jbm_dec.c b/lib_dec/ivas_jbm_dec.c index b19f0bdf7ecfc2b2729a803959e96120c27bc967..c97e5ff64783cba4f46ba1cca6336886f4d63f73 100644 --- a/lib_dec/ivas_jbm_dec.c +++ b/lib_dec/ivas_jbm_dec.c @@ -934,14 +934,90 @@ ivas_error ivas_jbm_dec_render( { ivas_jbm_dec_tc_buffer_playout( st_ivas, nSamplesAskedLocal, nSamplesRendered, p_output ); } +#ifdef FIX_1419_MONO_STEREO_UMX + else if ( st_ivas->ivas_format == MONO_FORMAT || st_ivas->ivas_format == STEREO_FORMAT ) +#else else if ( st_ivas->ivas_format == STEREO_FORMAT ) +#endif { +#ifdef FIX_1419_MONO_STEREO_UMX + *nSamplesRendered = min( st_ivas->hTcBuffer->n_samples_available, nSamplesAskedLocal ); +#endif + /* Rendering */ if ( st_ivas->renderer_type == RENDERER_MC ) { +#ifndef FIX_1419_MONO_STEREO_UMX *nSamplesRendered = min( st_ivas->hTcBuffer->n_samples_available, nSamplesAskedLocal ); +#endif ivas_ls_setup_conversion( st_ivas, st_ivas->nchan_transport, *nSamplesRendered, p_tc, p_output ); } +#ifdef FIX_1419_MONO_STEREO_UMX + else if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) + { + if ( st_ivas->ivas_format == MONO_FORMAT ) + { + /* routed to W */ + ivas_jbm_dec_tc_buffer_playout( st_ivas, nSamplesAskedLocal, nSamplesRendered, p_output ); + } + else if ( st_ivas->ivas_format == STEREO_FORMAT ) + { + for ( n = 0; n < *nSamplesRendered; n++ ) + { + p_output[0][n] = 0.5f * ( p_output[0][n] + p_output[1][n] ); /* W = 0.5 * ( L + R ) */ + p_output[1][n] = 0.5f * ( p_output[0][n] - p_output[1][n] ); /* Y = 0.5 * ( L - R ) */ + } + } + } + else if ( st_ivas->renderer_type == RENDERER_BINAURAL_OBJECTS_TD ) + { + /* Rendering for BINAURAL, BINAURAL_ROOM_REVERB and split rendering */ + if ( output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) + { + if ( ( error = ivas_td_binaural_renderer_sf_splitBinaural( st_ivas, p_output, *nSamplesRendered ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else + { + if ( ( error = ivas_td_binaural_renderer_sf( st_ivas, p_output, *nSamplesRendered ) ) != IVAS_ERR_OK ) + { + return error; + } + } + } + else if ( st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV_ROOM ) + { + /* Rendering for BINAURAL_ROOM_IR */ + if ( st_ivas->hDecoderConfig->Opt_Headrotation && st_ivas->ivas_format == MONO_FORMAT ) + { + /* Since rotation is performed on 7.1+4, we treat mono as 7.1+4 with other channels zero + * so move the mono content in index 0 to index 2 (center channel) */ + float *tmp; + tmp = p_output[2]; + p_output[2] = p_output[0]; + p_output[0] = tmp; + } + + if ( ( error = ivas_rend_crendProcessSubframe( st_ivas->hCrendWrapper, + st_ivas->intern_config, + st_ivas->hOutSetup.output_config, + st_ivas->hDecoderConfig, + st_ivas->hCombinedOrientationData, + &st_ivas->hIntSetup, + st_ivas->hEFAPdata, + st_ivas->hTcBuffer, + p_output, + p_output, + *nSamplesRendered, + output_Fs, + 0 ) ) != IVAS_ERR_OK ) + { + return error; + } + } +#endif } else if ( st_ivas->ivas_format == ISM_FORMAT ) { @@ -1928,11 +2004,15 @@ int16_t ivas_jbm_dec_get_num_tc_channels( ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; +#ifndef FIX_1419_MONO_STEREO_UMX /* since we support more output formats for mono, this is no longer sensible; leave it at the default from above */ if ( st_ivas->ivas_format == MONO_FORMAT ) { num_tc = st_ivas->hDecoderConfig->nchan_out; } else if ( st_ivas->ivas_format == STEREO_FORMAT && st_ivas->hDecoderConfig->nchan_out == 1 ) +#else + if ( st_ivas->ivas_format == STEREO_FORMAT && st_ivas->hDecoderConfig->nchan_out == 1 ) +#endif { num_tc = 1; } @@ -2800,7 +2880,11 @@ void ivas_dec_prepare_renderer( ivas_omasa_gain_masa_tc( st_ivas->hTcBuffer->tc, st_ivas->hMasaIsmData->gain_masa_edited, st_ivas->nchan_ism, st_ivas->hTcBuffer->n_samples_available ); } } +#ifdef FIX_1419_MONO_STEREO_UMX + else if ( st_ivas->ivas_format == MONO_FORMAT || st_ivas->ivas_format == STEREO_FORMAT ) +#else else if ( st_ivas->ivas_format == STEREO_FORMAT ) +#endif { ivas_jbm_dec_td_renderers_adapt_subframes( st_ivas ); } diff --git a/lib_dec/ivas_objectRenderer_internal.c b/lib_dec/ivas_objectRenderer_internal.c index ff47b1b9a77fa56f539ca737a201d2fff16f22b5..395d0f599783fae74161a4b385cdbbd5b72f30a9 100644 --- a/lib_dec/ivas_objectRenderer_internal.c +++ b/lib_dec/ivas_objectRenderer_internal.c @@ -66,8 +66,22 @@ ivas_error ivas_td_binaural_open( return IVAS_ERROR( IVAS_ERR_INTERNAL, "HRTF binary file present but not used in TD renderer" ); } +#ifdef FIX_1419_MONO_STEREO_UMX + return ivas_td_binaural_open_unwrap( &st_ivas->hHrtfTD, + st_ivas->hDecoderConfig->output_Fs, + num_src, + st_ivas->ivas_format, + st_ivas->transport_config, + st_ivas->hRenderConfig->directivity, + st_ivas->hRenderConfig->distAtt, + ( st_ivas->hRenderConfig != NULL ) ? &st_ivas->hRenderConfig->mono_stereo_upmix_config.radius : NULL, + st_ivas->hTransSetup, + &st_ivas->hBinRendererTd, + &st_ivas->binaural_latency_ns ); +#else return ivas_td_binaural_open_unwrap( &st_ivas->hHrtfTD, st_ivas->hDecoderConfig->output_Fs, num_src, st_ivas->ivas_format, st_ivas->transport_config, st_ivas->hRenderConfig->directivity, st_ivas->hRenderConfig->distAtt, st_ivas->hTransSetup, &st_ivas->hBinRendererTd, &st_ivas->binaural_latency_ns ); +#endif } @@ -312,6 +326,9 @@ ivas_error ivas_td_binaural_renderer_sf_splitBinaural( st_ivas->transport_config, st_ivas->hRenderConfig->directivity, st_ivas->hRenderConfig->distAtt, +#ifdef FIX_1419_MONO_STEREO_UMX + ( st_ivas->hRenderConfig != NULL ) ? &st_ivas->hRenderConfig->mono_stereo_upmix_config.radius : NULL, +#endif st_ivas->hTransSetup, &st_ivas->hTdRendHandles[i], &st_ivas->binaural_latency_ns ) ) != IVAS_ERR_OK ) diff --git a/lib_dec/ivas_output_config.c b/lib_dec/ivas_output_config.c index 17ce37c4d454239048bca6305d2f19337b12a030..14dd3e4942321cb31a296ee9ca2b519617341e0e 100644 --- a/lib_dec/ivas_output_config.c +++ b/lib_dec/ivas_output_config.c @@ -41,6 +41,49 @@ #endif #include "wmc_auto.h" +#ifdef FIX_1419_MONO_STEREO_UMX + +static void ms_bin_upmix_renderer_select( + const IVAS_FORMAT ivas_format, /* i : Decoder format */ + const IVAS_AUDIO_CONFIG output_config, /* i : Decoder output configuration */ + const IVAS_MS_UMX_CONF_HANDLE pMsUpmix_config, /* i : Mono/stereo upmix rendering configuration */ + const bool headrotation_enabled, /* i : Flag to signal headrotation is enabled */ + IVAS_AUDIO_CONFIG *internal_config, /* o : Internal configuration for rendering */ + RENDERER_TYPE *renderer_type /* o : Selected renderer type */ +) +{ + + *internal_config = ( ivas_format == MONO_FORMAT ) ? IVAS_AUDIO_CONFIG_MONO : IVAS_AUDIO_CONFIG_STEREO; + + /* spatial rendering disabled */ + if ( !pMsUpmix_config->spatialEnabled ) + { + if ( ivas_format == MONO_FORMAT ) + { + *renderer_type = RENDERER_NON_DIEGETIC_DOWNMIX; + } + else + { + *renderer_type = RENDERER_DISABLE; + } + return; + } + + /* spatial rendering configuration */ + if ( output_config == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) + { + if ( headrotation_enabled ) + { + *internal_config = IVAS_AUDIO_CONFIG_7_1_4; + } + *renderer_type = RENDERER_BINAURAL_MIXER_CONV_ROOM; + } + else /* HRIR based formats and split rendering */ + { + *renderer_type = RENDERER_BINAURAL_OBJECTS_TD; + } +} +#endif /*-------------------------------------------------------------------------* * ivas_renderer_select() @@ -78,7 +121,20 @@ void ivas_renderer_select( if ( output_config == IVAS_AUDIO_CONFIG_BINAURAL || output_config == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR || output_config == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB || output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) { +#ifdef FIX_1419_MONO_STEREO_UMX + if ( st_ivas->ivas_format == MONO_FORMAT || st_ivas->ivas_format == STEREO_FORMAT ) + { + ms_bin_upmix_renderer_select( st_ivas->ivas_format, + output_config, + &st_ivas->hRenderConfig->mono_stereo_upmix_config, + ( st_ivas->hDecoderConfig->Opt_Headrotation || st_ivas->hDecoderConfig->Opt_ExternalOrientation ), + internal_config, + renderer_type ); + } + else if ( st_ivas->ivas_format == ISM_FORMAT ) +#else if ( st_ivas->ivas_format == ISM_FORMAT ) +#endif { if ( st_ivas->ism_mode == ISM_MODE_PARAM ) { @@ -236,6 +292,45 @@ void ivas_renderer_select( * Non-binaural rendering configurations *-----------------------------------------------------------------*/ +#ifdef FIX_1419_MONO_STEREO_UMX + else if ( st_ivas->ivas_format == MONO_FORMAT || st_ivas->ivas_format == STEREO_FORMAT ) + { + *internal_config = ( st_ivas->ivas_format == MONO_FORMAT ) ? IVAS_AUDIO_CONFIG_MONO : IVAS_AUDIO_CONFIG_STEREO; + switch ( output_config ) + { + case IVAS_AUDIO_CONFIG_FOA: + case IVAS_AUDIO_CONFIG_HOA2: + case IVAS_AUDIO_CONFIG_HOA3: + *renderer_type = RENDERER_SBA_LINEAR_ENC; + break; + case IVAS_AUDIO_CONFIG_5_1: + case IVAS_AUDIO_CONFIG_7_1: + case IVAS_AUDIO_CONFIG_5_1_2: + case IVAS_AUDIO_CONFIG_5_1_4: + case IVAS_AUDIO_CONFIG_7_1_4: + case IVAS_AUDIO_CONFIG_LS_CUSTOM: + *renderer_type = RENDERER_MC; + break; + case IVAS_AUDIO_CONFIG_MONO: + if ( *internal_config == IVAS_AUDIO_CONFIG_STEREO ) + { + /* stereo to mono downmix */ + *renderer_type = RENDERER_MC; + } + break; + case IVAS_AUDIO_CONFIG_STEREO: + if ( *internal_config == IVAS_AUDIO_CONFIG_MONO ) + { + /* mono to stereo upmix */ + *renderer_type = RENDERER_NON_DIEGETIC_DOWNMIX; + } + break; + default: + /* RENDERER_DISABLE already set by default */ + break; + } + } +#else else if ( st_ivas->ivas_format == MONO_FORMAT ) { if ( output_config == IVAS_AUDIO_CONFIG_STEREO ) @@ -250,6 +345,7 @@ void ivas_renderer_select( *renderer_type = RENDERER_MC; } } +#endif else if ( st_ivas->ivas_format == ISM_FORMAT ) { if ( ( output_config == IVAS_AUDIO_CONFIG_STEREO ) && ( st_ivas->hDecoderConfig->Opt_non_diegetic_pan ) ) diff --git a/lib_dec/lib_dec.c b/lib_dec/lib_dec.c index fc63961eda08cc6e81624ab2d2bb6d13171749ad..17fbdc9c1be4d9149954d6147e88af7db18ef0c9 100644 --- a/lib_dec/lib_dec.c +++ b/lib_dec/lib_dec.c @@ -474,8 +474,19 @@ ivas_error IVAS_DEC_Configure( return IVAS_ERR_WRONG_PARAMS; } +#ifdef FIX_1419_MONO_STEREO_UMX + if ( hIvasDec->mode == IVAS_DEC_MODE_EVS && + ( outputConfig == IVAS_AUDIO_CONFIG_INVALID || + outputConfig == IVAS_AUDIO_CONFIG_ISM1 || + outputConfig == IVAS_AUDIO_CONFIG_ISM2 || + outputConfig == IVAS_AUDIO_CONFIG_ISM3 || + outputConfig == IVAS_AUDIO_CONFIG_ISM4 || + outputConfig == IVAS_AUDIO_CONFIG_MASA1 || + outputConfig == IVAS_AUDIO_CONFIG_MASA2 ) ) +#else /* we now support all output formats, so this validation is redundant */ if ( hIvasDec->mode == IVAS_DEC_MODE_EVS && !( ( outputConfig == IVAS_AUDIO_CONFIG_MONO && !non_diegetic_pan_enabled ) || ( outputConfig == IVAS_AUDIO_CONFIG_STEREO && non_diegetic_pan_enabled ) ) ) +#endif { return IVAS_ERR_WRONG_MODE; } @@ -876,6 +887,16 @@ ivas_error IVAS_DEC_FeedFrame_Serial( { hIvasDec->st_ivas->hDecoderConfig->ivas_total_brate = ACELP_8k00; +#ifdef FIX_1419_MONO_STEREO_UMX + if ( hIvasDec->st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || + hIvasDec->st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) + { + /* necessary to set up correct amount of memory for rendering; remaining setup happens in ivas_dec_setup_all() */ + ISAR_PRE_REND_GetMultiBinPoseData( &hIvasDec->st_ivas->hRenderConfig->split_rend_config, + &hIvasDec->st_ivas->hSplitBinRend->splitrend.multiBinPoseData, + ( hIvasDec->st_ivas->hCombinedOrientationData != NULL ) ? hIvasDec->st_ivas->hCombinedOrientationData->sr_pose_pred_axis : DEFAULT_AXIS ); + } +#endif if ( ( error = ivas_init_decoder( hIvasDec->st_ivas ) ) != IVAS_ERR_OK ) { return error; @@ -1721,6 +1742,10 @@ ivas_error IVAS_DEC_PrepareRenderer( IVAS_DEC_HANDLE hIvasDec /* i/o: IVAS decoder handle */ ) { +#ifdef FIX_1419_MONO_STEREO_UMX + ivas_error error; + +#endif if ( hIvasDec == NULL || hIvasDec->st_ivas == NULL ) { return IVAS_ERR_UNEXPECTED_NULL_POINTER; @@ -1730,6 +1755,18 @@ ivas_error IVAS_DEC_PrepareRenderer( { ivas_dec_prepare_renderer( hIvasDec->st_ivas ); } +#ifdef FIX_1419_MONO_STEREO_UMX + + if ( hIvasDec->st_ivas->hRenderConfig != NULL ) + { + if ( ( error = ms_upmix_validate_config( &hIvasDec->st_ivas->hRenderConfig->mono_stereo_upmix_config, + hIvasDec->st_ivas->ivas_format, + hIvasDec->st_ivas->hDecoderConfig->output_config ) ) != IVAS_ERR_OK ) + { + return error; + } + } +#endif hIvasDec->hasBeenPreparedRendering = true; @@ -2349,7 +2386,12 @@ static ivas_error ivas_dec_setup_all( { ivas_error error; +#ifdef FIX_1419_MONO_STEREO_UMX + /* split rendering related functions in else are required also for mono SR */ + if ( hIvasDec->mode == IVAS_DEC_MODE_EVS && splitRendBits == NULL ) +#else if ( hIvasDec->mode == IVAS_DEC_MODE_EVS ) +#endif { if ( hIvasDec->st_ivas->renderer_type == RENDERER_NON_DIEGETIC_DOWNMIX ) { @@ -2387,7 +2429,11 @@ static ivas_error ivas_dec_setup_all( * - reconfigure the decoder when the number of TC or IVAS total bitrate change *----------------------------------------------------------------*/ +#ifdef FIX_1419_MONO_STEREO_UMX + if ( st_ivas->bfi == 0 && hIvasDec->mode != IVAS_DEC_MODE_EVS ) +#else if ( st_ivas->bfi == 0 ) +#endif { if ( ( error = ivas_dec_setup( st_ivas ) ) != IVAS_ERR_OK ) { @@ -3220,6 +3266,11 @@ static ivas_error copyRendererConfigStruct( mvr2r( hRCin->roomAcoustics.pAcoustic_dsr, hRCout->roomAcoustics.pAcoustic_dsr, CLDFB_NO_CHANNELS_MAX ); mvr2r( hRCin->directivity, hRCout->directivity, 3 * MAX_NUM_OBJECTS ); mvr2r( hRCin->distAtt, hRCout->distAtt, 3 ); +#ifdef FIX_1419_MONO_STEREO_UMX + + /* Mono/Stereo upmix configuration */ + hRCout->mono_stereo_upmix_config = hRCin->mono_stereo_upmix_config; +#endif hRCout->split_rend_config = hRCin->split_rend_config; @@ -3373,6 +3424,28 @@ ivas_error IVAS_DEC_FeedRenderConfig( mvr2r( renderConfig.directivity, hRenderConfig->directivity, 3 * MAX_NUM_OBJECTS ); mvr2r( renderConfig.distAtt, hRenderConfig->distAtt, 3 ); +#ifdef FIX_1419_MONO_STEREO_UMX + + /* Mono/Stereo upmix configuration */ + if ( renderConfig.mono_stereo_upmix_config.spatialEnabled ) + { + /* copy data */ + hRenderConfig->mono_stereo_upmix_config.spatialEnabled = renderConfig.mono_stereo_upmix_config.spatialEnabled; + hRenderConfig->mono_stereo_upmix_config.radius = renderConfig.mono_stereo_upmix_config.radius; + hRenderConfig->mono_stereo_upmix_config.stereoLR = renderConfig.mono_stereo_upmix_config.stereoLR; + + mvr2r( renderConfig.mono_stereo_upmix_config.azi, hRenderConfig->mono_stereo_upmix_config.azi, 2 ); + mvr2r( renderConfig.mono_stereo_upmix_config.ele, hRenderConfig->mono_stereo_upmix_config.ele, 2 ); + + /* validate configuration early - repeated in IVAS_DEC_PrepareRenderer when input format is available */ + if ( ( error = ms_upmix_validate_config( &hRenderConfig->mono_stereo_upmix_config, + st_ivas->ivas_format, + st_ivas->hDecoderConfig->output_config ) ) != IVAS_ERR_OK ) + { + return error; + } + } +#endif hRenderConfig->split_rend_config = renderConfig.split_rend_config; @@ -4670,7 +4743,11 @@ static ivas_error evs_dec_main( { DEC_CORE_HANDLE *hCoreCoder; float mixer_left, mixer_rigth; +#ifdef FIX_1419_MONO_STEREO_UMX /* required now that mono can render to a higher number of output channels */ + float *p_output[MAX_TRANSPORT_CHANNELS]; +#else float *p_output[MAX_OUTPUT_CHANNELS_IN_DIEGETIC_PAN]; +#endif int16_t ch, nOutSamples; ivas_error error; @@ -4680,9 +4757,19 @@ static ivas_error evs_dec_main( mdct_switching_dec( hCoreCoder[0] ); +#ifdef FIX_1419_MONO_STEREO_UMX + for ( ch = 0; ch < MAX_TRANSPORT_CHANNELS; ch++ ) +#else for ( ch = 0; ch < MAX_OUTPUT_CHANNELS_IN_DIEGETIC_PAN; ch++ ) +#endif { p_output[ch] = st_ivas->p_output_f[ch]; +#ifdef FIX_1419_MONO_STEREO_UMX + if ( p_output[ch] != NULL ) + { + set_zero( p_output[ch], L_FRAME48k ); + } +#endif } /* run the main EVS decoding routine */ diff --git a/lib_rend/ivas_crend.c b/lib_rend/ivas_crend.c index 91346675023091f478cd4a637e93d0347e1d052e..880f3735ac2e35d66b7cd66f8522181423d834d3 100644 --- a/lib_rend/ivas_crend.c +++ b/lib_rend/ivas_crend.c @@ -167,6 +167,9 @@ static ivas_error ivas_rend_initCrend( const AUDIO_CONFIG outConfig, HRTFS_CREND_HANDLE hHrtfCrend, const int16_t ext_rend_flag, +#ifdef FIX_1419_MONO_STEREO_UMX + const int16_t bin_upmix_stereolr_flag, +#endif const int32_t output_Fs ) { int16_t i, j, tmp, tmp2; @@ -228,8 +231,15 @@ static ivas_error ivas_rend_initCrend( { if ( inConfigType == IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED ) { - hHrtf->max_num_ir -= 1; /* subtract LFE */ - hHrtf->gain_lfe = GAIN_LFE; +#ifdef FIX_1419_MONO_STEREO_UMX + if ( inConfig != IVAS_AUDIO_CONFIG_MONO && inConfig != IVAS_AUDIO_CONFIG_STEREO ) + { +#endif + hHrtf->max_num_ir -= 1; /* subtract LFE */ + hHrtf->gain_lfe = GAIN_LFE; +#ifdef FIX_1419_MONO_STEREO_UMX + } +#endif if ( output_Fs == 48000 ) { @@ -338,7 +348,20 @@ static ivas_error ivas_rend_initCrend( for ( i = 0; i < hHrtf->max_num_ir; i++ ) { +#ifdef FIX_1419_MONO_STEREO_UMX + if ( inConfig == IVAS_AUDIO_CONFIG_MONO ) + { + tmp = channelIndex_CICP1[i]; + } + else if ( inConfig == IVAS_AUDIO_CONFIG_STEREO ) + { + /* flag to select ±90 loudspeakers instead of ±30 */ + tmp = ( bin_upmix_stereolr_flag ) ? channelIndex_LR[i] : channelIndex_CICP2[i]; + } + else if ( inConfig == IVAS_AUDIO_CONFIG_5_1 ) +#else if ( inConfig == IVAS_AUDIO_CONFIG_5_1 ) +#endif { tmp = channelIndex_CICP6[i]; } @@ -360,7 +383,11 @@ static ivas_error ivas_rend_initCrend( } else { +#ifdef FIX_1419_MONO_STEREO_UMX + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Error: Invalid channel configuration for Crend!\n\n" ); +#else return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Error: Channel configuration not specified!\n\n" ); +#endif } if ( output_Fs == 48000 ) @@ -703,8 +730,15 @@ static ivas_error ivas_rend_initCrend( { if ( inConfigType == IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED ) { - hHrtf->max_num_ir -= 1; /* subtract LFE */ - hHrtf->gain_lfe = GAIN_LFE; +#ifdef FIX_1419_MONO_STEREO_UMX + if ( inConfig != IVAS_AUDIO_CONFIG_MONO && inConfig != IVAS_AUDIO_CONFIG_STEREO ) + { +#endif + hHrtf->max_num_ir -= 1; /* subtract LFE */ + hHrtf->gain_lfe = GAIN_LFE; +#ifdef FIX_1419_MONO_STEREO_UMX + } +#endif } if ( ext_rend_flag == 1 ) @@ -747,7 +781,20 @@ static ivas_error ivas_rend_initCrend( for ( i = 0; i < hHrtf->max_num_ir; i++ ) { +#ifdef FIX_1419_MONO_STEREO_UMX + if ( inConfig == IVAS_AUDIO_CONFIG_MONO ) + { + tmp = channelIndex_CICP1[i]; + } + else if ( inConfig == IVAS_AUDIO_CONFIG_STEREO ) + { + /* flag to select ±90 loudspeakers instead of ±30 */ + tmp = ( bin_upmix_stereolr_flag ) ? channelIndex_LR[i] : channelIndex_CICP2[i]; + } + else if ( inConfig == IVAS_AUDIO_CONFIG_5_1 ) +#else if ( inConfig == IVAS_AUDIO_CONFIG_5_1 ) +#endif { tmp = channelIndex_CICP6[i]; } @@ -1172,7 +1219,17 @@ ivas_error ivas_rend_openCrend( if ( ( *pCrend )->hHrtfCrend == NULL ) { +#ifdef FIX_1419_MONO_STEREO_UMX + if ( ( error = ivas_rend_initCrend( *pCrend, + inConfig, + outConfig, + hHrtfCrend, + ext_rend_flag, + ( hRendCfg != NULL ) ? hRendCfg->mono_stereo_upmix_config.stereoLR : 0, + output_Fs ) ) != IVAS_ERR_OK ) +#else if ( ( error = ivas_rend_initCrend( *pCrend, inConfig, outConfig, hHrtfCrend, ext_rend_flag, output_Fs ) ) != IVAS_ERR_OK ) +#endif { return error; } diff --git a/lib_rend/ivas_objectRenderer.c b/lib_rend/ivas_objectRenderer.c index a4e15c79dea1ae54e130d550b50e21d8c296049a..3473eb42afc8ae8678097c9752d4fcde1e37d36d 100644 --- a/lib_rend/ivas_objectRenderer.c +++ b/lib_rend/ivas_objectRenderer.c @@ -60,13 +60,16 @@ static void angles_to_vec( const float radius, const float azimuth, const float *---------------------------------------------------------------------*/ ivas_error ivas_td_binaural_open_unwrap( - TDREND_HRFILT_FiltSet_t **hHrtfTD, /* i/o: HR filter model (from file or NULL) */ - const int32_t output_Fs, /* i : Output sampling rate */ - const int16_t nchan_transport, /* i : Number of channels */ - const IVAS_FORMAT ivas_format, /* i : IVAS format (ISM/MC) */ - const AUDIO_CONFIG transport_config, /* i : Transport configuration */ - const float *directivity, /* i : Directivity pattern (used for ISM) */ - const float *distAtt, /* i : Distance attenuation (used for ISM) */ + TDREND_HRFILT_FiltSet_t **hHrtfTD, /* i/o: HR filter model (from file or NULL) */ + const int32_t output_Fs, /* i : Output sampling rate */ + const int16_t nchan_transport, /* i : Number of channels */ + const IVAS_FORMAT ivas_format, /* i : IVAS format (ISM/MC) */ + const AUDIO_CONFIG transport_config, /* i : Transport configuration */ + const float *directivity, /* i : Directivity pattern (used for ISM) */ + const float *distAtt, /* i : Distance attenuation (used for ISM) */ +#ifdef FIX_1419_MONO_STEREO_UMX + const float *radius_ms_umx, /* i : Radius (used for mono/stereo upmix) */ +#endif const IVAS_OUTPUT_SETUP hTransSetup, /* i : Loudspeaker layout */ BINAURAL_TD_OBJECT_RENDERER_HANDLE *hBinRendererTd, /* o : TD renderer handle */ int32_t *binaural_latency_ns /* i : Binauralization delay */ @@ -77,6 +80,9 @@ ivas_error ivas_td_binaural_open_unwrap( int16_t nS; int16_t SrcInd[MAX_NUM_TDREND_CHANNELS]; const float *ls_azimuth, *ls_elevation; +#ifdef FIX_1419_MONO_STEREO_UMX + float radius; +#endif float Pos[3]; float Dir[3]; TDREND_DirAtten_t *DirAtten_p; @@ -138,10 +144,22 @@ ivas_error ivas_td_binaural_open_unwrap( } } +#ifdef FIX_1419_MONO_STEREO_UMX + if ( ivas_format == MONO_FORMAT || ivas_format == STEREO_FORMAT || ivas_format == MC_FORMAT ) +#else if ( ivas_format == MC_FORMAT ) +#endif { switch ( transport_config ) { +#ifdef FIX_1419_MONO_STEREO_UMX + case IVAS_AUDIO_CONFIG_MONO: + case IVAS_AUDIO_CONFIG_STEREO: + /* appropriate values are set in ivas_init_decoder() */ + ls_azimuth = hTransSetup.ls_azimuth; + ls_elevation = hTransSetup.ls_elevation; + break; +#endif case IVAS_AUDIO_CONFIG_5_1: ls_azimuth = ls_azimuth_CICP6; ls_elevation = ls_elevation_CICP6; @@ -175,8 +193,21 @@ ivas_error ivas_td_binaural_open_unwrap( for ( nS = 0; nS < nchan_rend; nS++ ) { +#ifdef FIX_1419_MONO_STEREO_UMX + /* set radius from render configuration file for mono/stereo upmix; otherwise 1.f */ + radius = 1.f; + if ( ( transport_config == IVAS_AUDIO_CONFIG_MONO || transport_config == IVAS_AUDIO_CONFIG_STEREO ) && + radius_ms_umx != NULL ) + { + radius = *radius_ms_umx; + } + + /* Set source positions according to loudspeaker layout */ + angles_to_vec( radius, ls_azimuth[nS], ls_elevation[nS], Pos ); +#else /* Set source positions according to loudspeaker layout */ angles_to_vec( 1.0f, ls_azimuth[nS], ls_elevation[nS], Pos ); +#endif Dir[0] = 1.0f; Dir[1] = 0.0f; Dir[2] = 0.0f; @@ -710,7 +741,21 @@ ivas_error ivas_td_binaural_open_ext( distAtt = hRendCfg->distAtt; } +#ifdef FIX_1419_MONO_STEREO_UMX + return ivas_td_binaural_open_unwrap( pTDRend->hHrtfTD, + outFs, + nchan_transport, + ivas_format, + transport_config, + directivity, + distAtt, + ( hRendCfg != NULL ) ? &hRendCfg->mono_stereo_upmix_config.radius : NULL, + hTransSetup, + &pTDRend->hBinRendererTd, + &pTDRend->binaural_latency_ns ); +#else return ivas_td_binaural_open_unwrap( pTDRend->hHrtfTD, outFs, nchan_transport, ivas_format, transport_config, directivity, distAtt, hTransSetup, &pTDRend->hBinRendererTd, &pTDRend->binaural_latency_ns ); +#endif } diff --git a/lib_rend/ivas_output_init.c b/lib_rend/ivas_output_init.c index 01e1d77231ff06fc84f35a4ca20448a53e8b2729..33843aaba6482dffafaa38713bbe5c5cfb3a3c77 100644 --- a/lib_rend/ivas_output_init.c +++ b/lib_rend/ivas_output_init.c @@ -36,7 +36,13 @@ #include "prot.h" #include "ivas_prot_rend.h" #include "ivas_rom_com.h" +#ifdef FIX_1419_MONO_STEREO_UMX +#include "ivas_rom_rend.h" +#endif #include "ivas_prot.h" +#ifdef FIX_1419_MONO_STEREO_UMX +#include +#endif #include #ifdef DEBUGGING #include "debug.h" @@ -166,9 +172,17 @@ void ivas_output_init( { case IVAS_AUDIO_CONFIG_MONO: hOutSetup->is_loudspeaker_setup = 1; +#ifdef FIX_1419_MONO_STEREO_UMX + hOutSetup->is_planar_setup = 1; + hOutSetup->ls_azimuth = ls_azimuth_CICP1; + hOutSetup->ls_elevation = ls_elevation_CICP1; +#endif break; case IVAS_AUDIO_CONFIG_STEREO: hOutSetup->is_loudspeaker_setup = 1; +#ifdef FIX_1419_MONO_STEREO_UMX + hOutSetup->is_planar_setup = 1; +#endif hOutSetup->ls_azimuth = ls_azimuth_CICP2; hOutSetup->ls_elevation = ls_elevation_CICP2; break; @@ -276,10 +290,24 @@ int16_t ivas_get_nchan_buffers_dec( if ( st_ivas->ivas_format == MONO_FORMAT ) { nchan_out_buff = st_ivas->hDecoderConfig->nchan_out; +#ifdef FIX_1419_MONO_STEREO_UMX + if ( output_config == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR && + ( st_ivas->hDecoderConfig->Opt_Headrotation || st_ivas->hDecoderConfig->Opt_ExternalOrientation ) ) + { + nchan_out_buff = max( nchan_out_buff, st_ivas->hIntSetup.nchan_out_woLFE + st_ivas->hIntSetup.num_lfe ); + } +#endif } else if ( st_ivas->ivas_format == STEREO_FORMAT ) { nchan_out_buff = max( st_ivas->hDecoderConfig->nchan_out, CPE_CHANNELS ); +#ifdef FIX_1419_MONO_STEREO_UMX + if ( output_config == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR && + ( st_ivas->hDecoderConfig->Opt_Headrotation || st_ivas->hDecoderConfig->Opt_ExternalOrientation ) ) + { + nchan_out_buff = max( nchan_out_buff, st_ivas->hIntSetup.nchan_out_woLFE + st_ivas->hIntSetup.num_lfe ); + } +#endif } else if ( st_ivas->ivas_format == ISM_FORMAT ) { @@ -435,6 +463,115 @@ ivas_error ivas_output_buff_dec( return IVAS_ERR_OK; } +#ifdef FIX_1419_MONO_STEREO_UMX + +/*---------------------------------------------------------------------* + * ms_upmix_validate_config() + * + * + *---------------------------------------------------------------------*/ + +ivas_error ms_upmix_validate_config( + IVAS_MS_UMX_CONF_HANDLE pMsUpmixConfig, /* i/o: Mono/Stereo upmix configuration */ + const IVAS_FORMAT ivasFormat, /* i : IVAS Decoder input configuration */ + const IVAS_AUDIO_CONFIG outConfig /* i : IVAS Decoder output configuration */ +) +{ + int16_t i; + float azi_abs[2]; + float ele_abs[2]; + + if ( pMsUpmixConfig == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + /* skip validation if non spatial; values aren't used */ + if ( !pMsUpmixConfig->spatialEnabled ) + { + return IVAS_ERR_OK; + } + + /* validate radius */ + if ( pMsUpmixConfig->radius < 0.f || pMsUpmixConfig->radius > 15.75f ) + { + return IVAS_ERROR( IVAS_ERR_INVALID_RENDER_CONFIG, "Radius must be between 0 and 15.75" ); + } + + /* zero radius corresponds to non-spatial */ + if ( pMsUpmixConfig->radius == 0.f ) + { + pMsUpmixConfig->spatialEnabled = FALSE; + return IVAS_ERR_OK; + } + + /* obtain absolute values */ + for ( i = 0; i < 2; i++ ) + { + azi_abs[i] = fabsf( pMsUpmixConfig->azi[i] ); + ele_abs[i] = fabsf( pMsUpmixConfig->ele[i] ); + } + + /* validate speaker positions */ + if ( ivasFormat == MONO_FORMAT ) + { + if ( azi_abs[0] != 0 ) + { + return IVAS_ERROR( IVAS_ERR_INVALID_RENDER_CONFIG, "Mono cannot be panned" ); + } + if ( ele_abs[0] != 0 ) + { + return IVAS_ERROR( IVAS_ERR_INVALID_RENDER_CONFIG, "Mono cannot be panned" ); + } + } + else if ( ivasFormat == STEREO_FORMAT ) + { + if ( outConfig == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) + { + /* validate provided positions match BRIR */ + if ( ( azi_abs[0] != 30 && azi_abs[0] != 90 ) || + ( azi_abs[1] != 30 && azi_abs[1] != 90 ) ) + { + return IVAS_ERROR( IVAS_ERR_INVALID_RENDER_CONFIG, "BINAURAL_ROOM_IR only supports ±30 and ±90 degree azimuth" ); + } + if ( ele_abs[0] != 0 || ele_abs[1] != 0 ) + { + return IVAS_ERROR( IVAS_ERR_INVALID_RENDER_CONFIG, "BINAURAL_ROOM_IR does not allow nonzero elevation" ); + } + + /* flag to select ±90 azi loudspeakers */ + if ( azi_abs[0] == 90 && azi_abs[1] == 90 ) + { + pMsUpmixConfig->stereoLR = TRUE; + } + } + else /* HRIR based formats and split rendering */ + { + /* enforce symmetry */ + if ( pMsUpmixConfig->azi[0] != -pMsUpmixConfig->azi[1] ) + { + return IVAS_ERROR( IVAS_ERR_INVALID_RENDER_CONFIG, "Panning stereo pair with asymmetric azimuth is not allowed" ); + } + if ( pMsUpmixConfig->ele[0] != pMsUpmixConfig->ele[1] ) + { + return IVAS_ERROR( IVAS_ERR_INVALID_RENDER_CONFIG, "Panning stereo pair with differring elevation is not allowed" ); + } + + /* restrict values */ + if ( ( azi_abs[0] > 90 ) || ( azi_abs[1] > 90 ) ) + { + return IVAS_ERROR( IVAS_ERR_INVALID_RENDER_CONFIG, "Panning stereo pair beyond |90| degrees azimuth is not allowed" ); + } + if ( ( ele_abs[0] > 45 ) || ( ele_abs[1] > 45 ) ) + { + return IVAS_ERROR( IVAS_ERR_INVALID_RENDER_CONFIG, "Panning stereo pair beyond |45| degrees of elevation is not allowed" ); + } + } + } + + return IVAS_ERR_OK; +} +#endif /*---------------------------------------------------------------------* * is_split_rendering_enabled() diff --git a/lib_rend/ivas_prot_rend.h b/lib_rend/ivas_prot_rend.h index ae80304ee04ae85ea7bf3e40026aa3718a8004a0..224b393c48faf97d7c963909baa093769665f5b0 100644 --- a/lib_rend/ivas_prot_rend.h +++ b/lib_rend/ivas_prot_rend.h @@ -651,6 +651,9 @@ ivas_error ivas_td_binaural_open_unwrap( const AUDIO_CONFIG transport_config, /* i : Transport configuration */ const float *directivity, /* i : Directivity pattern (used for ISM) */ const float *distAtt, /* i : Distance attenuation (used for ISM) */ +#ifdef FIX_1419_MONO_STEREO_UMX + const float *radius_ms_umx, /* i : Radius (used for mono/stereo upmix) */ +#endif const IVAS_OUTPUT_SETUP hTransSetup, /* i : Loudspeaker layout */ BINAURAL_TD_OBJECT_RENDERER_HANDLE *hBinRendererTd, /* o : TD renderer handle */ int32_t *binaural_latency_ns /* i : Binauralization delay */ @@ -1343,6 +1346,13 @@ ivas_error ivas_render_config_init_from_rom( RENDER_CONFIG_HANDLE *hRenderConfig /* i/o: Renderer config handle */ ); +#ifdef FIX_1419_MONO_STEREO_UMX +ivas_error ms_upmix_validate_config( + IVAS_MS_UMX_CONF_HANDLE pMsUpmixConfig, /* i/o: Mono/Stereo upmix configuration */ + const IVAS_FORMAT ivasFormat, /* i : IVAS Decoder input configuration */ + const IVAS_AUDIO_CONFIG outConfig /* i : IVAS Decoder output configuration */ +); +#endif /*----------------------------------------------------------------------------------* * Quaternion operations diff --git a/lib_rend/ivas_render_config.c b/lib_rend/ivas_render_config.c index c3a39b426e39a0c1f372a5e0f88464c1c7e4c18b..e1290b54a760340dfe93674e817af8aff3d4e4a1 100644 --- a/lib_rend/ivas_render_config.c +++ b/lib_rend/ivas_render_config.c @@ -135,6 +135,15 @@ ivas_error ivas_render_config_init_from_rom( ( *hRenderConfig )->distAtt[0] = 15.75f; /* Default max dist */ ( *hRenderConfig )->distAtt[1] = 1.0f; /* Default ref dist */ ( *hRenderConfig )->distAtt[2] = 1.0f; /* Default rolloff factor */ +#ifdef FIX_1419_MONO_STEREO_UMX + + /* Mono/Stereo upmix configuration */ + ( *hRenderConfig )->mono_stereo_upmix_config.spatialEnabled = FALSE; + ( *hRenderConfig )->mono_stereo_upmix_config.stereoLR = FALSE; + ( *hRenderConfig )->mono_stereo_upmix_config.radius = 0.f; + set_zero( &( *hRenderConfig )->mono_stereo_upmix_config.azi[0], 2 ); + set_zero( &( *hRenderConfig )->mono_stereo_upmix_config.ele[0], 2 ); +#endif /* ISAR-related parameters */ ( *hRenderConfig )->split_rend_config.splitRendBitRate = ISAR_MAX_SPLIT_REND_BITRATE; diff --git a/lib_rend/ivas_rom_rend.c b/lib_rend/ivas_rom_rend.c index 3f4b906bd6fdaa8159f22abe9ed3fb2686c3fd6e..924f685adb0d07302bef9dd176f246e5ff6e278e 100644 --- a/lib_rend/ivas_rom_rend.c +++ b/lib_rend/ivas_rom_rend.c @@ -205,6 +205,11 @@ const int16_t sba_map_tc_512[11] = * 13 = 135, 35 * 14 = -135, 35 */ +#ifdef FIX_1419_MONO_STEREO_UMX +const int16_t channelIndex_CICP1[1] = { 2 }; +const int16_t channelIndex_CICP2[2] = { 0, 1 }; +const int16_t channelIndex_LR[2] = { 7, 8 }; +#endif const int16_t channelIndex_CICP6[5] = { 0, 1, 2, 5, 6 }; const int16_t channelIndex_CICP12[7] = { 0, 1, 2, 5, 6, 3, 4 }; const int16_t channelIndex_CICP14[7] = { 0, 1, 2, 5, 6, 9, 10 }; @@ -388,8 +393,8 @@ const float ivas_reverb_default_DSR[IVAS_REVERB_DEFAULT_N_BANDS] = *----------------------------------------------------------------------------------*/ /* CICP1 - Mono */ -const float ls_azimuth_CICP1[1] = { 0.0f }; -const float ls_elevation_CICP1[1] = { 0.0f }; +const float ls_azimuth_CICP1[1] = { 0.0f }; +const float ls_elevation_CICP1[1] = { 0.0f }; /*----------------------------------------------------------------------------------* @@ -619,6 +624,15 @@ const LS_CONVERSION_MATRIX ls_conversion_cicp19_cicp16[] = }; /* Upmix matrices */ +#ifdef FIX_1419_MONO_STEREO_UMX +const LS_CONVERSION_MATRIX ls_conversion_mono_cicpX[] = { + /* First row indicates the number of non-zero elements and the number of matrix columns */ + {1, 12.0f}, + /* Index of non-zero element, value of non-zero element*/ + {2, 1.0f}, +}; + +#endif const LS_CONVERSION_MATRIX ls_conversion_cicp12_cicp14[] = { /* First row indicates the number of non-zero elements and the number of matrix columns */ @@ -704,6 +718,9 @@ const LS_CONVERSION_MATRIX ls_conversion_cicp16_cicp19[] = const LS_CONVERSION_MAPPING ls_conversion_mapping[LS_SETUP_CONVERSION_NUM_MAPPINGS] = { /* Dowmix mappings - NULL is a special case for MONO / STEREO downmix */ +#ifdef FIX_1419_MONO_STEREO_UMX + {IVAS_AUDIO_CONFIG_STEREO, IVAS_AUDIO_CONFIG_MONO, NULL}, +#endif {IVAS_AUDIO_CONFIG_5_1, IVAS_AUDIO_CONFIG_MONO, NULL}, {IVAS_AUDIO_CONFIG_7_1, IVAS_AUDIO_CONFIG_MONO, NULL}, {IVAS_AUDIO_CONFIG_5_1_2, IVAS_AUDIO_CONFIG_MONO, NULL}, @@ -731,6 +748,14 @@ const LS_CONVERSION_MAPPING ls_conversion_mapping[LS_SETUP_CONVERSION_NUM_MAPPIN {IVAS_AUDIO_CONFIG_7_1_4, IVAS_AUDIO_CONFIG_5_1_4, ls_conversion_cicp19_cicp16}, /* Upmix mappings - NULL implies a 1:1 upmix */ +#ifdef FIX_1419_MONO_STEREO_UMX + {IVAS_AUDIO_CONFIG_MONO, IVAS_AUDIO_CONFIG_5_1, ls_conversion_mono_cicpX}, + {IVAS_AUDIO_CONFIG_MONO, IVAS_AUDIO_CONFIG_7_1, ls_conversion_mono_cicpX}, + {IVAS_AUDIO_CONFIG_MONO, IVAS_AUDIO_CONFIG_5_1_2, ls_conversion_mono_cicpX}, + {IVAS_AUDIO_CONFIG_MONO, IVAS_AUDIO_CONFIG_5_1_4, ls_conversion_mono_cicpX}, + {IVAS_AUDIO_CONFIG_MONO, IVAS_AUDIO_CONFIG_7_1_4, ls_conversion_mono_cicpX}, + +#endif {IVAS_AUDIO_CONFIG_STEREO, IVAS_AUDIO_CONFIG_5_1, NULL}, {IVAS_AUDIO_CONFIG_STEREO, IVAS_AUDIO_CONFIG_7_1, NULL}, {IVAS_AUDIO_CONFIG_STEREO, IVAS_AUDIO_CONFIG_5_1_2, NULL}, diff --git a/lib_rend/ivas_rom_rend.h b/lib_rend/ivas_rom_rend.h index 927287ecd96a2b33cb061c32d40013623da77469..2373f80ed09b72df057148019e89e60842f195b7 100644 --- a/lib_rend/ivas_rom_rend.h +++ b/lib_rend/ivas_rom_rend.h @@ -67,6 +67,11 @@ extern const int16_t sba_map_tc_512[11]; * FASTCONV and PARAMETRIC binaural renderer ROM tables *----------------------------------------------------------------------------------*/ +#ifdef FIX_1419_MONO_STEREO_UMX +extern const int16_t channelIndex_CICP1[1]; +extern const int16_t channelIndex_CICP2[2]; +extern const int16_t channelIndex_LR[2]; +#endif extern const int16_t channelIndex_CICP6[5]; extern const int16_t channelIndex_CICP12[7]; extern const int16_t channelIndex_CICP14[7]; diff --git a/lib_rend/ivas_rotation.c b/lib_rend/ivas_rotation.c index b9286d3d96b01ae9bddcb24319badb17319c024c..c4c30ac160673028cc6918489fec3c975e05d419 100644 --- a/lib_rend/ivas_rotation.c +++ b/lib_rend/ivas_rotation.c @@ -361,7 +361,11 @@ void rotateFrame_sd( ) { int16_t i, j; +#ifdef FIX_1419_MONO_STEREO_UMX + int16_t nchan, num_lfe, index_lfe; +#else int16_t nchan, index_lfe; +#endif int16_t ch_in, ch_in_woLFE, ch_out, ch_out_woLFE; int16_t azimuth, elevation; @@ -374,6 +378,9 @@ void rotateFrame_sd( push_wmops( "rotateFrame_sd" ); nchan = hTransSetup.nchan_out_woLFE + hTransSetup.num_lfe; +#ifdef FIX_1419_MONO_STEREO_UMX + num_lfe = hTransSetup.num_lfe; +#endif index_lfe = hTransSetup.index_lfe[0]; tmp = 1.0f / ( subframe_len - 1 ); @@ -400,7 +407,11 @@ void rotateFrame_sd( } /* input channel index without LFE */ +#ifdef FIX_1419_MONO_STEREO_UMX + ch_in_woLFE = ( ( num_lfe > 0 ) && ( ch_in >= index_lfe ) ) ? ch_in - 1 : ch_in; +#else ch_in_woLFE = ( ch_in >= index_lfe ) ? ch_in - 1 : ch_in; +#endif /* gains for previous subframe rotation */ rotateAziEle( hTransSetup.ls_azimuth[ch_in_woLFE], hTransSetup.ls_elevation[ch_in_woLFE], &azimuth, &elevation, hCombinedOrientationData->Rmat_prev[0], hTransSetup.is_planar_setup ); @@ -417,7 +428,12 @@ void rotateFrame_sd( } /* output channel index without LFE */ +#ifdef FIX_1419_MONO_STEREO_UMX + ch_out_woLFE = ( ( num_lfe > 0 ) && ( ch_out >= index_lfe ) ) ? ch_out - 1 : ch_out; +#else ch_out_woLFE = ( ch_out >= index_lfe ) ? ch_out - 1 : ch_out; +#endif + gains_prev[ch_in][ch_out] = tmp_gains[ch_out_woLFE]; } @@ -439,7 +455,11 @@ void rotateFrame_sd( } /* output channel index without LFE */ +#ifdef FIX_1419_MONO_STEREO_UMX + ch_out_woLFE = ( ( num_lfe > 0 ) && ( ch_out >= index_lfe ) ) ? ch_out - 1 : ch_out; +#else ch_out_woLFE = ( ch_out >= index_lfe ) ? ch_out - 1 : ch_out; +#endif gains[ch_in][ch_out] = tmp_gains[ch_out_woLFE]; } diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 4bb1024aae19eae7aa5e70822b9296b8052eef83..87cd2771842841b700e99a6512e77b059bfe3c07 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -6229,7 +6229,8 @@ static ivas_error renderMcToBinaural( } } - if ( ( inConfig == IVAS_AUDIO_CONFIG_LS_CUSTOM ) || ( combinedOrientationEnabled && ( inConfig == IVAS_AUDIO_CONFIG_5_1 || inConfig == IVAS_AUDIO_CONFIG_7_1 ) ) ) + if ( ( inConfig == IVAS_AUDIO_CONFIG_LS_CUSTOM ) || + ( combinedOrientationEnabled && ( inConfig == IVAS_AUDIO_CONFIG_5_1 || inConfig == IVAS_AUDIO_CONFIG_7_1 ) ) ) { copyBufferTo2dArray( mcInput->base.inputBuffer, tmpRendBuffer ); diff --git a/lib_util/render_config_reader.c b/lib_util/render_config_reader.c index 7729efbc7cb0ffe9ca4174f7aa12ea7012c5a67c..01bff48ac33b3eb99ff728b46f6ab8f09152283e 100644 --- a/lib_util/render_config_reader.c +++ b/lib_util/render_config_reader.c @@ -2591,6 +2591,46 @@ ivas_error RenderConfigReader_read( free( pValue ); acIdx++; } +#ifdef FIX_1419_MONO_STEREO_UMX + else if ( strcmp( chapter, "MSUPMIX" ) == 0 && strlen( pParams ) != 0 ) + { + params_idx = 0; + pValue = (char *) calloc( strlen( pParams ), sizeof( char ) ); + while ( sscanf( pParams + params_idx, "%64[^=]=%[^;];", item, pValue ) == 2 ) + { + params_idx += (int32_t) ( strlen( item ) + strlen( pValue ) + 2 ); + if ( strcmp( item, "AZIMUTH" ) == 0 ) + { + if ( read_txt_vector( pValue, 2, &hRenderConfig->mono_stereo_upmix_config.azi[0] ) ) + { + errorHandler( item, ERROR_VALUE_INVALID ); + return IVAS_ERR_INVALID_RENDER_CONFIG; + } + /* set flag to signal that spatial rendering is enabled */ + hRenderConfig->mono_stereo_upmix_config.spatialEnabled = 1; + } + else if ( strcmp( item, "ELEVATION" ) == 0 ) + { + if ( read_txt_vector( pValue, 2, &hRenderConfig->mono_stereo_upmix_config.ele[0] ) ) + { + errorHandler( item, ERROR_VALUE_INVALID ); + return IVAS_ERR_INVALID_RENDER_CONFIG; + } + /* set flag to signal that spatial rendering is enabled */ + hRenderConfig->mono_stereo_upmix_config.spatialEnabled = 1; + } + else if ( strcmp( item, "RADIUS" ) == 0 ) + { + if ( !sscanf( pValue, "%f", &hRenderConfig->mono_stereo_upmix_config.radius ) ) + { + errorHandler( item, ERROR_VALUE_INVALID ); + } + /* set flag to signal that spatial rendering is enabled */ + hRenderConfig->mono_stereo_upmix_config.spatialEnabled = 1; + } + } + } +#endif else if ( strcmp( chapter, "SPLITREND" ) == 0 && strlen( pParams ) != 0 ) { params_idx = 0; @@ -2976,6 +3016,14 @@ ivas_error RenderConfigReader_getAcousticEnvironment( { return IVAS_ERR_UNEXPECTED_NULL_POINTER; } +#ifdef FIX_1419_MONO_STEREO_UMX + + /* case when config file contains no acoustic environment, the defaults are already set from ROM */ + if ( id == 65535 && pRenderConfigReader->nAE == 0 ) + { + return IVAS_ERR_OK; + } +#endif /* case when -aeid is not specified, select first ID from config file */ if ( id == 65535 && pRenderConfigReader->nAE > 0 )