Commit 1c43063a authored by Sandesh Venkatesh's avatar Sandesh Venkatesh
Browse files

Converted the sba to binaural path for renderer_input_sba function

parent 5d66cda9
Loading
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -1559,6 +1559,9 @@ int main(
    free( inFloatBuffer );
    free( outInt16Buffer );
    free( outFloatBuffer );
#ifdef IVAS_FLOAT_FIXED
    free( outInt32Buffer );
#endif
    for ( i = 0; i < RENDERER_MAX_MASA_INPUTS; ++i )
    {
        MasaFileReader_close( &masaReaders[i] );
+333 −2
Original line number Diff line number Diff line
@@ -37,7 +37,12 @@
#include "ivas_prot_rend.h"
#include "wmc_auto.h"
#include <assert.h>

#ifdef IVAS_FLOAT_FIXED
#define ATTACK_CNST_48k (2106670080) //Q31
#define ATTACK_CNST_32k ( 2086555136 ) // Q31
#define ATTACK_CNST_16k ( 2027355264 ) // Q31
#define ATTACK_CNST_8k  ( 1913946752 ) // Q31
#endif

/*-------------------------------------------------------------------*
 * detect_strong_saturations()
@@ -93,7 +98,65 @@ static int16_t detect_strong_saturations(

    return apply_strong_limiting;
}
#ifdef IVAS_FLOAT_FIXED
/*-------------------------------------------------------------------*
 * detect_strong_saturations()
 *
 * Detection of very strong saturations,
 * usually happens as a consequence of a heavy corrupted bitstream
 *-------------------------------------------------------------------*/

/*! r: apply_strong_limiting flag */
static Word16 detect_strong_saturations_fx(
    const Word16 BER_detect,        /* i  : BER detect flag                 */
    Word16 *strong_saturation_cnt, /* i/o: counter of strong saturations   */
    const Word32 max_val,            /* i  : maximum absolute value          */
    Word16 *frame_gain,               /* i/o: frame gain value                */
    Word16 q_factor                /*Q factor of the output samples*/
)
{
    Word16 apply_strong_limiting;
    Word32 compare_max_value_Mul_3, compare_max_value_Mul_10;

    apply_strong_limiting = 0;
    compare_max_value_Mul_3 = L_lshl(98187,q_factor); // 3 * IVAS_LIMITER_THRESHOLD
    compare_max_value_Mul_10 = L_lshl( 327290, q_factor );//10 * IVAS_LIMITER_THRESHOLD
    IF ( BER_detect )
    {
        *strong_saturation_cnt = 50;
        apply_strong_limiting = 1;
    }
    ELSE IF( GT_32( max_val , compare_max_value_Mul_3) && GT_16(*strong_saturation_cnt , 0 ))
    {
        apply_strong_limiting = 1;
    }
    ELSE IF( GT_32 (max_val , compare_max_value_Mul_10) )
    {
        *strong_saturation_cnt += 20;
        *strong_saturation_cnt = min( *strong_saturation_cnt, 50 );
        apply_strong_limiting = 1;
    }
    else
    {
        ( *strong_saturation_cnt )--;
        *strong_saturation_cnt = max( *strong_saturation_cnt, 0 );
    }

    if ( apply_strong_limiting )
    {
        IF( LT_16 (* frame_gain , 4915) ) // Q14 of 0.3 is compared
        {
            //*frame_gain /= 3.0f;
            *frame_gain = lshr(divide1616( *frame_gain, 24576 ) , 2);//Q14
        }
        ELSE
        {
            apply_strong_limiting = 0;
        }
    }

    return apply_strong_limiting;
}
/*-------------------------------------------------------------------*
 * ivas_limiter_open()
 *
@@ -109,7 +172,7 @@ ivas_error ivas_limiter_open(
{
    int16_t i;
    IVAS_LIMITER_HANDLE hLimiter;

    Word32 attack_cnst_fx = 0;
    if ( max_num_channels <= 0 || sampling_rate <= 0 )
    {
        return ( IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Wrong parameters for Limiter\n" ) );
@@ -127,22 +190,96 @@ ivas_error ivas_limiter_open(
    {
        return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Limiter handle\n" ) );
    }
    if ( ( hLimiter->channel_ptrs_fx = malloc( max_num_channels * sizeof( Word32 * ) ) ) == NULL )
    {
        return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Limiter handle\n" ) );
    }
    hLimiter->sampling_rate = sampling_rate;
    hLimiter->gain = 1.f;
    hLimiter->gain_fx = ONE_IN_Q14;
    hLimiter->release_heuristic = 0.f;
    hLimiter->release_heuristic_fx = 0;
    hLimiter->attack_constant = powf( 0.01f, 1.0f / ( IVAS_LIMITER_ATTACK_SECONDS * sampling_rate ) );
    SWITCH( sampling_rate )
    {
        case 48000:
            attack_cnst_fx = ATTACK_CNST_48k;
            BREAK;
        case 32000:
            attack_cnst_fx = ATTACK_CNST_32k;
            BREAK;
        case 16000:
            attack_cnst_fx = ATTACK_CNST_16k;
            BREAK;
        case 8000:
            attack_cnst_fx = ATTACK_CNST_8k;
            BREAK;
       

    }
    hLimiter->attack_constant_fx = attack_cnst_fx;
    hLimiter->strong_saturation_count = 0;

    for ( i = 0; i < max_num_channels; ++i )
    {
        hLimiter->channel_ptrs[i] = NULL;
        hLimiter->channel_ptrs_fx[i] = NULL;
    }

    *hLimiter_out = hLimiter;

    return IVAS_ERR_OK;
}
#else
/*-------------------------------------------------------------------*
 * ivas_limiter_open()
 *
 * Allocate and initialize limiter struct
 *-------------------------------------------------------------------*/

/*! r : limiter struct handle */
ivas_error ivas_limiter_open(
    IVAS_LIMITER_HANDLE *hLimiter_out, /* o  : limiter struct handle                           */
    const int16_t max_num_channels,    /* i  : maximum number of I/O channels to be processed  */
    const int32_t sampling_rate        /* i  : sampling rate for processing                    */
)
{
    int16_t i;
    IVAS_LIMITER_HANDLE hLimiter;

    if ( max_num_channels <= 0 || sampling_rate <= 0 )
    {
        return ( IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Wrong parameters for Limiter\n" ) );
    }

    if ( ( hLimiter = malloc( sizeof( IVAS_LIMITER ) ) ) == NULL )
    {
        return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Limiter handle\n" ) );
    }

    hLimiter->max_num_channels = max_num_channels;
    hLimiter->num_channels = max_num_channels;

    if ( ( hLimiter->channel_ptrs = malloc( max_num_channels * sizeof( float * ) ) ) == NULL )
    {
        return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Limiter handle\n" ) );
    }
    hLimiter->sampling_rate = sampling_rate;
    hLimiter->gain = 1.f;
    hLimiter->release_heuristic = 0.f;
    hLimiter->attack_constant = powf( 0.01f, 1.0f / ( IVAS_LIMITER_ATTACK_SECONDS * sampling_rate ) );
    hLimiter->strong_saturation_count = 0;

    for ( i = 0; i < max_num_channels; ++i )
    {
        hLimiter->channel_ptrs[i] = NULL;
    }

    *hLimiter_out = hLimiter;

    return IVAS_ERR_OK;
}
#endif

/*-------------------------------------------------------------------*
 * ivas_limiter_close()
@@ -206,7 +343,201 @@ void ivas_limiter_dec(
    return;
}

#ifdef IVAS_FLOAT_FIXED
/*-------------------------------------------------------------------*
 * limiter_process()
 *
 * hLimiter->channel_ptrs must be set before calling this function.
 * Consider using a wrapper function like ivas_limiter_dec() instead
 * of calling this directly.
 *-------------------------------------------------------------------*/

void limiter_process_fx(
    IVAS_LIMITER_HANDLE hLimiter,  /* i/o: limiter struct handle                                              */
    const Word16 output_frame,    /* i  : number of samples to be processed per channel in the I/O buffer    */
    const Word32 threshold,         /* i  : signal amplitude above which limiting starts to be applied         */
    const Word16 BER_detect,       /* i  : BER detect flag                                                    */
    Word16 *strong_saturation_cnt, /* i/o: counter of strong saturations (can be NULL)                        */
    Word16 q_factor                /*Q factor of output samples*/
)
{
    Word16 i, c;
    Word32 tmp, max_val;
    Word32 *sample;
    Word32  attack_constant;
    Word32 releaseHeuristic;
    Word16 apply_limiting, apply_strong_limiting;
    Word32 **output;
    Word16 num_channels, q_fact_gain, div32, release_constant, compare_value;
    Word32 sampling_rate;
    Word16 gain, frame_gain, fact, fact_2, exp_pow, exp_pow_2, result;
    Word32 mul;
    Word32 mul_2;
    /* return early if given nonsensical values */
    IF ( hLimiter == NULL || output_frame <= 0 )
    {
        return;
    }

    apply_limiting = 1;
    apply_strong_limiting = 0;

    gain = hLimiter->gain_fx;
    output = hLimiter->channel_ptrs_fx;
    num_channels = hLimiter->num_channels;
    sampling_rate = hLimiter->sampling_rate;
    attack_constant = hLimiter->attack_constant_fx;

    /*-----------------------------------------------------------------*
     * Find highest absolute peak sample value
     *-----------------------------------------------------------------*/

    max_val = 0;

    FOR ( i = 0; i < output_frame; i++ )
    {
        FOR( c = 0; c < num_channels; c++ )
        {
            tmp = L_abs( output[c][i] );
            IF ( GT_32(tmp , max_val) )
            {
                max_val = tmp;
            }
        }
    }

    /* Release heuristic
     *
     * Value ranging from 0.f to 1.f. Increases on each frame that contains
     * a sample with a value above threshold and decreases on each frame
     * with all sample values below threshold.
     *
     * Values of 0 and 1 map to the shortest and longest release time, respectively.
     *
     * The goal of this heuristic is to avoid the "pumping" effect when only
     * sharp transients exceed the threshold (use short release time), but also
     * keep the gain curve smoother if the threshold is exceeded in many frames
     * in a short span of time.
     */
    Word16 sample_num = 0;
    SWITCH (sampling_rate)
    {
        case 48000:
            sample_num = L_SUBFRAME_48k;
            BREAK;
        case 32000:
            sample_num = L_SUBFRAME_32k;
            BREAK;
        case 16000:
            sample_num = L_SUBFRAME_16k;
            BREAK;
        case 8000:
            sample_num = L_SUBFRAME_8k;
            BREAK;


    }
    releaseHeuristic = hLimiter->release_heuristic_fx;
    q_fact_gain = Q14;
    if ( max_val > threshold )
    {
        frame_gain = shr(divide3232( threshold, max_val ),1);//to q14
        releaseHeuristic = min( ONE_IN_Q30, L_add( releaseHeuristic, 21474836 ) );
       // release_constant = powf( 0.01f, 1.0f / ( 0.005f * powf( 200.f, .02 ) * sampling_rate ) );
        /* Unoptimized code for reference */
        /* releaseHeuristic = min( 1.f, releaseHeuristic + ( (float) 2.f * output_frame / sampling_rate / adaptiveReleaseWindowLengthInSeconds ) );
         *                                                            ^
         *                                                          React faster when release time should be increased
         */
    }
    else
    {
        releaseHeuristic = max( 0, L_sub( releaseHeuristic, 53687091 ) );
        /* Unoptimized code for reference */
        /*releaseHeuristic = max( 0.f, releaseHeuristic - ( (float) 0.5f * output_frame / sampling_rate / adaptiveReleaseWindowLengthInSeconds ) );
         *                                                            ^
         *                                                          React slower when release time should be decreased
         */
        /* No samples above threshold and gain from previous frame is already 1.f,
         * therefore gain == 1.f for the entire frame. Skip processing. */
        if ( gain >= ( lshl( 1, q_fact_gain ) ))
        {
            apply_limiting = 0;
        }
        /* No samples above threshold but gain from previous frame is not 1.f,
         * transition to gain == 1.f */
        frame_gain = lshl( 1, q_fact_gain );
        
    }
    
    /* Detection of very strong saturations */
    if ( strong_saturation_cnt != NULL )
    {
        apply_strong_limiting = detect_strong_saturations_fx( BER_detect, strong_saturation_cnt, max_val, &frame_gain, q_factor );
    }
    compare_value = 3277;//Q14 of 0.1f
    /* Limit gain reduction to 20dB. Any peaks that require gain reduction
     * higher than this are most likely due to bit errors during decoding */
    if ( frame_gain < compare_value && !apply_strong_limiting )
    {
        frame_gain = compare_value;
    }

    if ( apply_limiting )
    {       
        /* 99% time constants of the gain curve
         *
         * The denominator of the second argument determines after how many
         * samples the gain curve will reach 99% of its target value
         */
        mul = Mpy_32_32( 1025941011, releaseHeuristic ) >> 10; // Q16
        /*For powf(200.0f,x)*/
        fact = L_Extract_lc( mul, &exp_pow );
        result = extract_l( Pow2( 14, fact ) );
        div32 = divide3232( L_lshl( 1, ( 14 - exp_pow + 1 ) ), L_mult( result, sample_num ) );
        /*For powf(0.01f,x)*/
        mul_2 = L_mult( -13607, div32 ) >> 10; // Q16
        fact_2 = L_Extract_lc( mul_2, &exp_pow_2 );
        release_constant = extract_l( Pow2( 2, fact_2 ) ); //-(Q2+exp_pow_2)

        /* Unoptimized code for reference */
        /* releaseTimeInSeconds = 0.005f * powf(200.f, releaseHeuristic); <-- Map heuristic value (0; 1) exponentially to range (0.005; 1)
         * release_constant = powf( 0.01f, 1.0f / ( releaseTimeInSeconds * sampling_rate ) );
         */

        /*-----------------------------------------------------------------*
         * Apply limiting
         *-----------------------------------------------------------------*/

        for ( i = 0; i < output_frame; i++ )
        {
            /* Update gain */
            if ( frame_gain < gain )
            {
                gain = add(extract_h(Mpy_32_16_r(attack_constant ,( sub(gain , frame_gain) ))) , frame_gain);//q14
            }
            else
            {
                gain = add(extract_l(L_lshr( L_mult( release_constant , sub( gain, frame_gain ) ), ( Q2 - exp_pow_2 ) )) , frame_gain);//q14
            }

            for ( c = 0; c < num_channels; c++ )
            {
                sample = &output[c][i];

                /* Apply gain */
                *sample = Mpy_32_16_r(L_lshl( *sample,1 ),gain ) ;//q_factor
            }
        }
    }

    /* Save last gain and release heuristic values for next frame */
    hLimiter->gain_fx = gain;
    hLimiter->release_heuristic_fx = releaseHeuristic;

    return;
}
#endif
/*-------------------------------------------------------------------*
 * limiter_process()
 *
+17 −3
Original line number Diff line number Diff line
@@ -127,7 +127,16 @@ void limiter_process(
    const int16_t BER_detect,                                   /* i  : BER detect flag                                                 */
    int16_t *strong_saturation_cnt                              /* i/o: counter of strong saturations (can be NULL)                     */
);

#ifdef IVAS_FLOAT_FIXED
void limiter_process_fx(
    IVAS_LIMITER_HANDLE hLimiter,                               /* i/o: limiter struct handle                                           */
    const Word16 output_frame,                                 /* i  : number of samples to be processed per channel in the I/O buffer */
    const Word32 threshold,                                      /* i  : signal amplitude above which limiting starts to be applied      */
    const Word16 BER_detect,                                   /* i  : BER detect flag                                                 */
    Word16 *strong_saturation_cnt,                              /* i/o: counter of strong saturations (can be NULL)                     */
    Word16 q_factor
    );
#endif
/*----------------------------------------------------------------------------------*
 * TD decorr. function prototypes
 *----------------------------------------------------------------------------------*/
@@ -1496,12 +1505,17 @@ void ivas_combined_orientation_update_index(
    COMBINED_ORIENTATION_HANDLE hCombinedOrientationData,       /* i/o: combined orientation handle                     */
    const int16_t samples_rendered                              /* i  : samples rendered since the last call            */
);

#ifdef IVAS_FLOAT_FIXED
void ivas_combined_orientation_update_start_index(
    COMBINED_ORIENTATION_HANDLE hCombinedOrientationData,       /* i/o: combined orientation handle                     */
    const Word16 samples_rendered                              /* i  : samples rendered since the last call            */
);
#else
void ivas_combined_orientation_update_start_index(
    COMBINED_ORIENTATION_HANDLE hCombinedOrientationData,       /* i/o: combined orientation handle                     */
    const int16_t samples_rendered                              /* i  : samples rendered since the last call            */
);

#endif
void ivas_combined_orientation_set_to_start_index(
    COMBINED_ORIENTATION_HANDLE hCombinedOrientationData        /* i/o: combined orientation handle                     */
);
+4 −0
Original line number Diff line number Diff line
@@ -371,6 +371,10 @@ ivas_error ivas_er_compute_reflections(
    /* If size is different, reallocate circ buffers */
    /* Otherwise allocate new circ buffers */
#ifdef IVAS_FLOAT_FIXED
    for ( i = 0; i < 150; i++ )
    {
       reflections->shoebox_data.gains.data_fx[i] = (Word32) float_to_fix( reflections->shoebox_data.gains.data[i], 15 );
    }
    if ( reflections->circ_buffers )
    {
        if ( reflections->circ_len == circ_len )
+65 −1
Original line number Diff line number Diff line
@@ -1761,7 +1761,18 @@ ivas_error combine_external_and_head_orientations(
    hCombinedOrientationData->cur_subframe_samples_rendered = 0;
    hCombinedOrientationData->subframe_idx_start = 0;
    hCombinedOrientationData->cur_subframe_samples_rendered_start = 0;

#ifdef IVAS_FLOAT_FIXED
    for ( Word16 k = 0; k < 4; k++ )
    {
        for ( i = 0; i < 3; i++ )
        {
            for ( j = 0; j < 3; j++ )
            {
                hCombinedOrientationData->Rmat_fx[k][i][j] = (Word32) float_to_fix( hCombinedOrientationData->Rmat[k][i][j], 30 );
            }
        }
    }
#endif
    return IVAS_ERR_OK;
}

@@ -2384,7 +2395,29 @@ void ivas_combined_orientation_update_index(

    return;
}
#ifdef IVAS_FLOAT_FIXED

/*-------------------------------------------------------------------------
 * ivas_combined_orientation_update_index()
 *
 * update read index based on the number of rendered samples
 *------------------------------------------------------------------------*/

void ivas_combined_orientation_set_to_start_index(
    COMBINED_ORIENTATION_HANDLE hCombinedOrientationData /* i/o: combined orientation handle    */
)
{
    IF ( hCombinedOrientationData != NULL )
    {
        hCombinedOrientationData->subframe_idx = hCombinedOrientationData->subframe_idx_start;
        move16();
        hCombinedOrientationData->cur_subframe_samples_rendered = hCombinedOrientationData->cur_subframe_samples_rendered_start;
        move16();
    }

    return;
}
#else

/*-------------------------------------------------------------------------
 * ivas_combined_orientation_update_index()
@@ -2404,8 +2437,38 @@ void ivas_combined_orientation_set_to_start_index(

    return;
}
#endif
#ifdef IVAS_FLOAT_FIXED
/*-------------------------------------------------------------------------
 * ivas_combined_orientation_update_start_index()
 *
 * update start index based on the number of rendered samples
 *------------------------------------------------------------------------*/

void ivas_combined_orientation_update_start_index(
    COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, /* i/o: combined orientation handle           */
    const Word16 samples_rendered                        /* i  : samples rendered since the last call  */
)
{
    IF ( hCombinedOrientationData != NULL )
    {
        IF ( hCombinedOrientationData->num_subframes == 1 )
        {
            /* only one orientation available anyway or split rendering with low resolution*/
            hCombinedOrientationData->subframe_idx = 0;
        }
        ELSE
        {
            hCombinedOrientationData->cur_subframe_samples_rendered_start += samples_rendered;
            hCombinedOrientationData->subframe_idx_start += hCombinedOrientationData->cur_subframe_samples_rendered / hCombinedOrientationData->subframe_size;
            hCombinedOrientationData->cur_subframe_samples_rendered_start = hCombinedOrientationData->cur_subframe_samples_rendered % hCombinedOrientationData->subframe_size;
            hCombinedOrientationData->subframe_idx_start = min( hCombinedOrientationData->subframe_idx, hCombinedOrientationData->num_subframes - 1 );
        }
    }

    return;
}
#else
/*-------------------------------------------------------------------------
 * ivas_combined_orientation_update_start_index()
 *
@@ -2435,3 +2498,4 @@ void ivas_combined_orientation_update_start_index(

    return;
}
#endif
 No newline at end of file
Loading