diff --git a/lib_com/ivas_ism_com.c b/lib_com/ivas_ism_com.c index bd064a584a3b91787faaf72f12631fb324873b8e..b4a058f1f4311dfe0fc1dfd1d5a0ef9ec2554f30 100644 --- a/lib_com/ivas_ism_com.c +++ b/lib_com/ivas_ism_com.c @@ -551,6 +551,10 @@ void ivas_param_ism_config( hParamIsm->last_el_sgn[i] = 1; } +#ifdef FIX_549_DMX_GAIN + hParamIsm->last_dmx_gain = 1.0f; + set_f( hParamIsm->last_cardioid_left, 1.0f, MAX_NUM_OBJECTS ); +#endif return; } diff --git a/lib_com/ivas_stat_com.h b/lib_com/ivas_stat_com.h index 7783ff5ec29b5357b5154708128c485ed8ac0750..51337f1c5cd79e35aae5242e3804638d60b080c3 100644 --- a/lib_com/ivas_stat_com.h +++ b/lib_com/ivas_stat_com.h @@ -169,6 +169,11 @@ typedef struct ivas_param_ism_data_structure int16_t noisy_speech_buffer[PARAM_ISM_HYS_BUF_SIZE]; int16_t flag_equal_energy; +#ifdef FIX_549_DMX_GAIN + float last_dmx_gain; + float last_cardioid_left[MAX_NUM_OBJECTS]; +#endif + } PARAM_ISM_CONFIG_DATA, *PARAM_ISM_CONFIG_HANDLE; diff --git a/lib_com/options.h b/lib_com/options.h index da7b1801785183f2409982d494ce69ec81cc169c..b57e3c1db0178d9c3e1eab19d430e05455811d7a 100755 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -158,6 +158,7 @@ #define FIX_557_CRASH_IN_ISM_DTX /* VA issue 557: fix crash in 1ISM 48 kbps DTX */ #define IGF_TUNING_96 /* FhG: Issue 546: slight tuning of IGF config used in 96 kbps stereo, 128 kbps SBA and others */ +#define FIX_549_DMX_GAIN /* FhG: issue 549: ParamISM output too quiet */ #define FIX_522_ISM_FIRST_SID /* VA: fix ISM decoder crash if first received frame is an SID */ diff --git a/lib_dec/ivas_ism_param_dec.c b/lib_dec/ivas_ism_param_dec.c index ff15bae70ddbc394c4d4b189445f62f3009fe79e..2497f5ab988c4a042367ec78e5f33961254d897d 100644 --- a/lib_dec/ivas_ism_param_dec.c +++ b/lib_dec/ivas_ism_param_dec.c @@ -713,6 +713,11 @@ void ivas_param_ism_dec( int16_t ch, nchan_transport, nchan_out, nchan_out_woLFE, i; int16_t subframe_idx, slot_idx, index_slot, bin_idx; int32_t ivas_total_brate; +#ifdef FIX_549_DMX_GAIN + int16_t output_frame; + float gain, ene_tc, ene_sum, grad; + float last_gain; +#endif float ref_power[CLDFB_NO_CHANNELS_MAX]; float cx_diag[CLDFB_NO_CHANNELS_MAX][PARAM_ISM_MAX_DMX]; /* CLDFB Input Buffers */ @@ -736,6 +741,12 @@ void ivas_param_ism_dec( /* Initialization */ hDirAC = st_ivas->hDirAC; assert( hDirAC ); +#ifdef FIX_549_DMX_GAIN + ene_tc = 0.0f; + ene_sum = 0.0f; + last_gain = st_ivas->hDirAC->hParamIsm->last_dmx_gain; + output_frame = (int16_t) ( st_ivas->hDecoderConfig->output_Fs / FRAMES_PER_SEC ); +#endif nchan_transport = st_ivas->nchan_transport; if ( st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_EXTERNAL ) @@ -819,6 +830,42 @@ void ivas_param_ism_dec( } } +#ifdef FIX_549_DMX_GAIN + /* Energy Compensation */ + for ( i = 0; i < output_frame; i++ ) + { + ene_tc += output_f[0][i] * output_f[0][i] + output_f[1][i] * output_f[1][i]; // L*L + R*R + ene_sum += ( output_f[0][i] + output_f[1][i] ) * ( output_f[0][i] + output_f[1][i] ); // (L+R)*(L+R) + } + gain = sqrtf( ene_tc / ( ene_sum + EPSILON ) ); + if ( st_ivas->hSCE[0]->hCoreCoder[0]->ini_frame > 1 ) + { + /* Smoothing */ + gain = 0.75f * gain + 0.25f * last_gain; + /* 10ms ramp */ + grad = ( gain - last_gain ) * 2.0f / (float) output_frame; /* slope between two consecutive gains, 480 samples length */ + for ( i = 0; i < ( output_frame / 2 ); i++ ) + { + output_f[0][i] *= ( last_gain + i * grad ); + output_f[1][i] *= ( last_gain + i * grad ); + } + for ( ; i < output_frame; i++ ) + { + output_f[0][i] *= gain; + output_f[1][i] *= gain; + } + } + else + { + for ( i = 0; i < output_frame; i++ ) + { + output_f[0][i] *= gain; + output_f[1][i] *= gain; + } + } + st_ivas->hDirAC->hParamIsm->last_dmx_gain = gain; +#endif + for ( ch = 0; ch < nchan_transport; ch++ ) { /*-----------------------------------------------------------------* @@ -1034,6 +1081,11 @@ void ivas_param_ism_dec_digest_tc( int16_t ch, nchan_transport, nchan_out, nchan_out_woLFE, i; int16_t slot_idx, bin_idx; int32_t ivas_total_brate; +#ifdef FIX_549_DMX_GAIN + int16_t output_frame; + float gain, ene_tc, ene_sum, grad; + float last_gain; +#endif float ref_power[CLDFB_NO_CHANNELS_MAX]; float cx_diag[CLDFB_NO_CHANNELS_MAX][PARAM_ISM_MAX_DMX]; /* Direct Response/EFAP Gains */ @@ -1043,6 +1095,12 @@ void ivas_param_ism_dec_digest_tc( /* Initialization */ hDirAC = st_ivas->hDirAC; assert( hDirAC ); +#ifdef FIX_549_DMX_GAIN + ene_tc = 0.0f; + ene_sum = 0.0f; + last_gain = st_ivas->hDirAC->hParamIsm->last_dmx_gain; + output_frame = (int16_t) ( st_ivas->hDecoderConfig->output_Fs / FRAMES_PER_SEC ); +#endif nchan_transport = st_ivas->nchan_transport; ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; @@ -1129,6 +1187,42 @@ void ivas_param_ism_dec_digest_tc( } } +#ifdef FIX_549_DMX_GAIN + /* Energy Compensation */ + for ( i = 0; i < output_frame; i++ ) + { + ene_tc += transport_channels_f[0][i] * transport_channels_f[0][i] + transport_channels_f[1][i] * transport_channels_f[1][i]; // L*L + R*R + ene_sum += ( transport_channels_f[0][i] + transport_channels_f[1][i] ) * ( transport_channels_f[0][i] + transport_channels_f[1][i] ); // (L+R)*(L+R) + } + gain = sqrtf( ene_tc / ( ene_sum + EPSILON ) ); + if ( st_ivas->hSCE[0]->hCoreCoder[0]->ini_frame > 1 ) + { + /* Smoothing */ + gain = 0.75f * gain + 0.25f * last_gain; + /* 10ms ramp */ + grad = ( gain - last_gain ) * 2.0f / (float) output_frame; /* slope between two consecutive gains, 480 samples length */ + for ( i = 0; i < ( output_frame / 2 ); i++ ) + { + transport_channels_f[0][i] *= ( last_gain + i * grad ); + transport_channels_f[1][i] *= ( last_gain + i * grad ); + } + for ( ; i < output_frame; i++ ) + { + transport_channels_f[0][i] *= gain; + transport_channels_f[1][i] *= gain; + } + } + else + { + for ( i = 0; i < output_frame; i++ ) + { + transport_channels_f[0][i] *= gain; + transport_channels_f[1][i] *= gain; + } + } + st_ivas->hDirAC->hParamIsm->last_dmx_gain = gain; +#endif + for ( ch = 0; ch < nchan_transport; ch++ ) { /*-----------------------------------------------------------------* diff --git a/lib_enc/ivas_ism_param_enc.c b/lib_enc/ivas_ism_param_enc.c index 7565bdcae65d7564ef52e3e905002a8635706d65..c3d50d24db4d73de5ceceb14aef7fda314b246e1 100644 --- a/lib_enc/ivas_ism_param_enc.c +++ b/lib_enc/ivas_ism_param_enc.c @@ -222,6 +222,11 @@ void ivas_param_ism_stereo_dmx( float alpha, azi_shift, tmp, tmp_1; float cardioid_left[MAX_NUM_OBJECTS], cardioid_right[MAX_NUM_OBJECTS]; float stereo_dmx[2][L_FRAME48k]; +#ifdef FIX_549_DMX_GAIN + float dmx_gain, ene_dmx, ene_data, grad; + float last_dmx_gain; + float last_cardioid_left; +#endif ISM_METADATA_HANDLE hIsmMetaData; push_wmops( "ivas_param_ism_st_dmx" ); @@ -229,6 +234,12 @@ void ivas_param_ism_stereo_dmx( /*Initialization*/ alpha = 0.5; azi_shift = 0; +#ifdef FIX_549_DMX_GAIN + dmx_gain = 0; + ene_dmx = 0; + ene_data = 0; + last_dmx_gain = st_ivas->hDirAC->hParamIsm->last_dmx_gain; +#endif /* Set the stereo dmx to zero */ set_zero( stereo_dmx[0], L_FRAME48k ); @@ -238,11 +249,14 @@ void ivas_param_ism_stereo_dmx( for ( i = 0; i < st_ivas->hEncoderConfig->nchan_ism; i++ ) { hIsmMetaData = st_ivas->hIsmMetaData[i]; - +#ifdef FIX_549_DMX_GAIN + last_cardioid_left = st_ivas->hDirAC->hParamIsm->last_cardioid_left[i]; +#endif /*Compute the Cardioids for the corresponding object direction */ tmp = hIsmMetaData->azimuth * ( EVS_PI / 180 ); tmp_1 = ( EVS_PI / 2 ) + azi_shift; cardioid_left[i] = alpha + ( 1 - alpha ) * cosf( tmp - tmp_1 ); +#ifndef FIX_549_DMX_GAIN cardioid_right[i] = alpha + ( 1 - alpha ) * cosf( tmp + tmp_1 ); /* Loop over all samples */ @@ -252,8 +266,83 @@ void ivas_param_ism_stereo_dmx( stereo_dmx[0][j] += cardioid_left[i] * tmp; /* DMX Left */ stereo_dmx[1][j] += cardioid_right[i] * tmp; /* DMX Right */ } +#else + if ( st_ivas->hSCE[0]->hCoreCoder[0]->ini_frame > 0 ) + { + float last_cardioid_right; + last_cardioid_right = 1.0f - last_cardioid_left; + /* Smoothing */ + cardioid_left[i] = 0.75f * cardioid_left[i] + 0.25f * last_cardioid_left; + grad = ( cardioid_left[i] - last_cardioid_left ) * 2.0f / (float) input_frame; /* for the right cardioid, multiply with -1 */ + /* Cardioids sum up to 1 */ + cardioid_right[i] = 1.0f - cardioid_left[i]; /* corresponds to: alpha + ( 1 - alpha ) * cosf( tmp + tmp_1 ); */ + /* Loop over all samples */ + for ( j = 0; j < input_frame / 2; j++ ) + { + tmp = data[i][j]; + stereo_dmx[0][j] += ( ( last_cardioid_left + j * grad ) * tmp ); /* DMX Left */ + stereo_dmx[1][j] += ( ( last_cardioid_right + j * grad * ( -1.0f ) ) * tmp ); /* DMX Right */ + ene_data += ( tmp * tmp ); /* energy of all objects combined */ + } + for ( ; j < input_frame; j++ ) + { + tmp = data[i][j]; + stereo_dmx[0][j] += cardioid_left[i] * tmp; /* DMX Left */ + stereo_dmx[1][j] += cardioid_right[i] * tmp; /* DMX Right */ + ene_data += ( tmp * tmp ); /* energy of all objects combined */ + } + } + else + { + /* Cardioids sum up to 1 */ + cardioid_right[i] = 1.0f - cardioid_left[i]; /* corresponds to: alpha + ( 1 - alpha ) * cosf( tmp + tmp_1 ); */ + /* Loop over all samples */ + for ( j = 0; j < input_frame; j++ ) + { + tmp = data[i][j]; + stereo_dmx[0][j] += cardioid_left[i] * tmp; /* DMX Left */ + stereo_dmx[1][j] += cardioid_right[i] * tmp; /* DMX Right */ + ene_data += ( tmp * tmp ); /* energy of all objects combined */ + } + } + st_ivas->hDirAC->hParamIsm->last_cardioid_left[i] = cardioid_left[i]; +#endif } +#ifdef FIX_549_DMX_GAIN + /* Energy compensation */ + for ( j = 0; j < input_frame; j++ ) + { + ene_dmx += stereo_dmx[0][j] * stereo_dmx[0][j] + stereo_dmx[1][j] * stereo_dmx[1][j]; + } + dmx_gain = sqrtf( ene_data / ( ene_dmx + EPSILON ) ); + /* Smoothing */ + if ( st_ivas->hSCE[0]->hCoreCoder[0]->ini_frame > 0 ) + { + dmx_gain = 0.75f * dmx_gain + 0.25f * last_dmx_gain; + /* 10ms ramp */ + grad = ( dmx_gain - last_dmx_gain ) * 2.0f / (float) input_frame; /* slope between two consecutive gains, 480 samples length */ + for ( i = 0; i < ( input_frame / 2 ); i++ ) + { + stereo_dmx[0][i] *= ( last_dmx_gain + i * grad ); + stereo_dmx[1][i] *= ( last_dmx_gain + i * grad ); + } + for ( ; i < input_frame; i++ ) + { + stereo_dmx[0][i] *= dmx_gain; + stereo_dmx[1][i] *= dmx_gain; + } + } + else + { + for ( j = 0; j < input_frame; j++ ) + { + stereo_dmx[0][j] *= dmx_gain; + stereo_dmx[1][j] *= dmx_gain; + } + } + st_ivas->hDirAC->hParamIsm->last_dmx_gain = dmx_gain; +#endif /* Copy the stereo dmx to data variable */ mvr2r( stereo_dmx[0], data[0], input_frame ); mvr2r( stereo_dmx[1], data[1], input_frame );