Commit ad1a2a99 authored by eichenseer's avatar eichenseer
Browse files

Issue 549: Downmix energy compensation for ParamISM to raise output levels.

parent 7c560c29
Loading
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -483,6 +483,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;
}

+5 −0
Original line number Diff line number Diff line
@@ -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;


+2 −0
Original line number Diff line number Diff line
@@ -185,6 +185,8 @@

#define FIX_528_ISM_MD_FILE_TOO_SHORT                   /* VA: issue 528: ISM Metadata file too short  */

#define FIX_549_DMX_GAIN                                /* FhG: issue 549: ParamISM output too quiet */


/* ################## End DEVELOPMENT switches ######################### */
/* clang-format on */
+94 −0
Original line number Diff line number Diff line
@@ -729,6 +729,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 */
@@ -752,6 +757,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 )
@@ -835,6 +846,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 / 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;
        }
    }
    *( last_gain ) = gain;
#endif

    for ( ch = 0; ch < nchan_transport; ch++ )
    {
        /*-----------------------------------------------------------------*
@@ -1055,6 +1102,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 */
@@ -1064,6 +1116,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;
@@ -1150,6 +1208,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 / 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;
        }
    }
    *( last_gain ) = gain;
#endif

    for ( ch = 0; ch < nchan_transport; ch++ )
    {
        /*-----------------------------------------------------------------*
+88 −0
Original line number Diff line number Diff line
@@ -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,13 @@ 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 );
    last_cardioid_left = &( st_ivas->hDirAC->hParamIsm->last_cardioid_left[0] );
#endif

    /* Set the stereo dmx to zero */
    set_zero( stereo_dmx[0], L_FRAME48k );
@@ -243,6 +255,7 @@ void ivas_param_ism_stereo_dmx(
        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 +265,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 )
        {
            /* Smoothing */
            cardioid_left[i] = 0.75f * cardioid_left[i] + 0.25f * *( last_cardioid_left );
            grad = ( cardioid_left[i] - *( last_cardioid_left ) ) * 2.0f / 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++ )
            {
                float last_cardioid_right;
                last_cardioid_right = 1.0f - *( last_cardioid_left );
                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 ) ) * tmp ); /* DMX Right */
            }
            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 */
            }
        }
        *( last_cardioid_left ) = cardioid_left[i];
        last_cardioid_left++;
#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 / 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;
        }
    }
    *( 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 );