Commit 9c9d846f authored by Jiaquan Huo's avatar Jiaquan Huo
Browse files

Reduce double precision in LFE PLC to single

parent e433c88c
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -5495,7 +5495,7 @@ void ivas_lfe_dec(

void ivas_lfe_tdplc( 
    LFE_DEC_HANDLE hLFE,                                        /* i/o: LFE decoder handle                      */
    const float *prevsynth,                                     /* i  : previous frame synthesis                */
    float *prevsynth,                                     /* i  : previous frame synthesis                */
    float *ytda,                                                /* o  : output time-domain buffer               */
    const int16_t output_frame                                  /* i  : output frame length                     */
);
+1 −1
Original line number Diff line number Diff line
@@ -3124,7 +3124,7 @@ const int16_t ivas_lfe_min_shift_tbl[IVAS_LFE_NUM_COEFFS_IN_SUBGRP] = { 1, 0 };
const float ivas_lfe_lpf_delay[2] = { 0.00175f, 0.0035f };
const double d_hamm_lfe_plc[LFE_PLC_LENANA / 2] =
const float d_hamm_lfe_plc[LFE_PLC_LENANA / 2] =
{
    0.08000000000000002, 0.08015895227847719, 0.08063569926248770, 0.08142991147368656, 0.08254104003450596, 0.08396831704748331, 0.08571075612595230, 0.08776715307573196,
    0.09013608672734141, 0.09281591991816535, 0.09580480062389246, 0.09910066323844335, 0.10270123000150438, 0.10660401257268071, 0.11080631375118072, 0.11530522933984272,
+1 −1
Original line number Diff line number Diff line
@@ -359,7 +359,7 @@ extern const int16_t ivas_lfe_min_shift_tbl[IVAS_LFE_NUM_COEFFS_IN_SUBGRP];
extern const ivas_lfe_freq_models ivas_str_lfe_freq_models;
extern const float ivas_lfe_lpf_delay[2];

extern const double d_hamm_lfe_plc[LFE_PLC_LENANA / 2];
extern const float d_hamm_lfe_plc[LFE_PLC_LENANA / 2];

extern const float ivas_sin_twiddle_480[IVAS_480_PT_LEN >> 1];
extern const float ivas_cos_twiddle_480[IVAS_480_PT_LEN >> 1];
+52 −181
Original line number Diff line number Diff line
@@ -52,114 +52,20 @@
#define LFE_PLC_RECLEN_48K ( ( IVAS_LFE_NUM_COEFFS_IN_SUBGRP + 1 ) * L_FRAME48k / IVAS_LFE_NUM_COEFFS_IN_SUBGRP + LFE_PLC_FDEL )
#define LFE_PLC_RECLEN     ( ( LFE_PLC_RECLEN_48K / LFE_PLC_DSF ) )
#define LFE_PLC_MUTE_THR   ( 10 )
#define LFE_PLC_BURST_ATT  ( pow( pow( 10.0, -3.0 / 20.0 ), 1.0 / ( LFE_PLC_FS * 0.02 ) ) ) /* attenuate 3dB per frame starting with 10th consecutive loss */
#define LFE_PLC_BURST_ATT  ( powf( powf( 10.0f, -3.0f / 20.0f ), 1.0f / ( LFE_PLC_FS * 20 / 1000 ) ) ) /* attenuate 3dB per frame starting with 10th consecutive loss */

#define MAX_LEN_LP 960

#define EPS_STOP 1e-5
#define EPS_STOP 1e-5f

/*------------------------------------------------------------------------------------------*
 * Static function declarations
 *
 * Note (DLB): the local double precision functions defined below are replica of corresponding
 * Note (DLB): the local float precision functions defined below are replica of corresponding
 * float functions defined in tools.c, lpc_tools.c and syn_filt.c.
 * Double precision arithmetic is required for proper functioning of the lfe_plc.
 * float precision arithmetic is required for proper functioning of the lfe_plc.
 *------------------------------------------------------------------------------------------*/

static void mvr2d(
    const float x[], /* i  : input vector  */
    double y[],      /* o  : output vector */
    const int16_t n  /* i  : vector size   */
)
{
    int16_t i;

    if ( n <= 0 )
    {
        /* cannot transfer vectors with size 0 */
        return;
    }

    for ( i = n - 1; i >= 0; i-- )
    {
        y[i] = x[i];
    }

    return;
}


/*---------------------------------------------------------------------*
 * autocorr()
 *
 * Compute autocorrelations of input signal
 *---------------------------------------------------------------------*/

static void d_autocorr(
    const double *x,        /* i  : input signal               */
    double *r,              /* o  : autocorrelations vector    */
    const int16_t m,        /* i  : order of LP filter         */
    const int16_t len,      /* i  : window size                */
    const double *wind,     /* i  : window                     */
    const int16_t rev_flag, /* i  : flag to reverse window     */
    const int16_t sym_flag, /* i  : symmetric window flag      */
    const int16_t no_thr    /* i  : flag to avoid thresholding */
)
{
    double t[MAX_LEN_LP];
    double s;
    int16_t i, j;

    /* Windowing of signal */
    if ( rev_flag == 1 )
    {
        /* time reversed window */
        for ( i = 0; i < len; i++ )
        {
            t[i] = x[i] * wind[len - i - 1];
        }
    }
    else if ( sym_flag == 1 )
    {
        /* symmetric window of even length */
        for ( i = 0; i < len / 2; i++ )
        {
            t[i] = x[i] * wind[i];
        }

        for ( ; i < len; i++ )
        {
            t[i] = x[i] * wind[len - 1 - i];
        }
    }
    else /* assymetric window */
    {
        for ( i = 0; i < len; i++ )
        {
            t[i] = x[i] * wind[i];
        }
    }

    /* Compute r[1] to r[m] */
    for ( i = 0; i <= m; i++ )
    {
        s = t[0] * t[i];
        for ( j = 1; j < len - i; j++ )
        {
            s += t[j] * t[i + j];
        }
        r[i] = s;
    }

    if ( r[0] < 100.0f && no_thr == 0 )
    {
        r[0] = 100.0f;
    }

    return;
}


/*---------------------------------------------------------------------*
 * lev_dur()
 *
@@ -169,21 +75,22 @@ static void d_autocorr(

/*! r: energy of prediction error   */
static int16_t d_lev_dur(
    double *a,       /* o  : LP coefficients (a[0] = 1.0) */
    const double *r, /* i  : vector of autocorrelations   */
    float *a_out,       /* o  : LP coefficients (a[0] = 1.0) */
    const float *r, /* i  : vector of autocorrelations   */
    const int16_t m, /* i  : order of LP filter           */
    double epsP[]    /* o  : prediction error energy      */
    float epsP[]    /* o  : prediction error energy      */
)
{
    int16_t i, j, l;
    double buf[TCXLTP_LTP_ORDER];
    double *rc; /* reflection coefficients  0,...,m-1 */
    double s, at, err;
    float buf[TCXLTP_LTP_ORDER];
    float *rc; /* reflection coefficients  0,...,m-1 */
    float s, at, err;
    int16_t flag = 0;
    float a[LFE_PLC_LPCORD + 1] = {0.f};

    rc = &buf[0];
    rc[0] = ( -r[1] ) / r[0];
    a[0] = 1.0;
    a[0] = 1.0f;
    a[1] = rc[0];
    err = r[0] + r[1] * rc[0];

@@ -195,7 +102,7 @@ static int16_t d_lev_dur(

    for ( i = 2; i <= m; i++ )
    {
        s = 0.0;
        s = 0.0f;
        for ( j = 0; j < i; j++ )
        {
            s += r[i - j] * a[j];
@@ -205,6 +112,14 @@ static int16_t d_lev_dur(
        if ( fabs( rc[i - 1] ) > 0.99945f )
        {
            flag = 1; /* Test for unstable filter. If unstable keep old A(z) */
            return flag;
        }
        else
        {
            for (j = 0; j < i; j++)
            {
                a_out[j] = a[j];
            }
        }
        for ( j = 1; j <= i / 2; j++ )
        {
@@ -239,14 +154,14 @@ static int16_t d_lev_dur(
 *-------------------------------------------------------------------*/

static uint16_t d_a2rc(
    const double *a,       /* i  : LPC coefficients            */
    double *refl,          /* o  : Reflection co-efficients    */
    const float *a,       /* i  : LPC coefficients            */
    float *refl,          /* o  : Reflection co-efficients    */
    const int16_t lpcorder /* i  : LPC order                   */
)
{
    double ff[LFE_PLC_LPCORD];
    float ff[LFE_PLC_LPCORD];
    int16_t m, j, n;
    double km, denom, x;
    float km, denom, x;

    for ( m = 0; m < lpcorder; m++ )
    {
@@ -257,18 +172,18 @@ static uint16_t d_a2rc(
    for ( m = lpcorder - 1; m >= 0; m-- )
    {
        km = ff[m];
        if ( km <= -1.0 || km >= 1.0 )
        if ( km <= -1.0f || km >= 1.0f )
        {
            for ( j = 0; j < lpcorder; j++ )
            {
                refl[j] = 0.0;
                refl[j] = 0.0f;
            }

            return 0;
        }

        refl[m] = -km;
        denom = 1.0 / ( 1.0 - km * km );
        denom = 1.0f / ( 1.0f - km * km );
        for ( j = 0; j < m / 2; j++ )
        {
            n = m - 1 - j;
@@ -286,50 +201,6 @@ static uint16_t d_a2rc(
    return 1;
}


static void d_syn_filt(
    const double a[], /* i  : LP filter coefficients                     */
    const int16_t m,  /* i  : order of LP filter                         */
    const float x[],  /* i  : input signal                               */
    float y[],        /* o  : output signal                              */
    const int16_t l,  /* i  : size of filtering                          */
    const float mem[] /* i  : initial filter states                      */
)
{
    int16_t i, j;
    double buf[LFE_PLC_LPCORD + LFE_PLC_RECLEN]; /* temporary synthesis buffer */
    double s, *yy;

    yy = &buf[0];

    /*------------------------------------------------------------------*
     * copy initial filter states into synthesis buffer and do synthesis
     *------------------------------------------------------------------*/
    for ( i = 0; i < m; i++ )
    {
        *yy++ = mem[i];
    }

    /*-----------------------------------------------------------------------*
     * Do the filtering
     *-----------------------------------------------------------------------*/

    for ( i = 0; i < l; i++ )
    {
        s = x[i];
        for ( j = 1; j <= m; j++ )
        {
            s -= a[j] * yy[i - j];
        }

        yy[i] = s;
        y[i] = (float) s;
    }

    return;
}


/*-----------------------------------------------------------------------------------------*
 * Function check_stab()
 *
@@ -337,16 +208,16 @@ static void d_syn_filt(
 *-----------------------------------------------------------------------------------------*/

static uint16_t check_stab(
    const double *a,
    double delta )
    const float *a,
    float delta )
{
    double amod[LFE_PLC_LPCORD], refl[LFE_PLC_LPCORD];
    float amod[LFE_PLC_LPCORD], refl[LFE_PLC_LPCORD];
    int16_t i;
    double fac;
    double fac1;
    float fac;
    float fac1;
    uint16_t stable;

    fac = 1.0 + delta;
    fac = 1.0f + delta;
    fac1 = fac;

    for ( i = 0; i < LFE_PLC_LPCORD; i++ )
@@ -366,16 +237,16 @@ static uint16_t check_stab(
 * Find maximum LPC filter sharpening by iteration to get a filter that is almost instable
 *-----------------------------------------------------------------------------------------*/

static double find_max_delta(
    double *a )
static float find_max_delta(
    float *a )
{
    double delta;
    double eps;
    float delta;
    float eps;
    uint16_t stable;
    double fac;
    float fac;

    delta = 0.0;
    eps = 0.01;
    delta = 0.0f;
    eps = 0.01f;
    fac = 2;
    stable = FALSE;

@@ -385,7 +256,7 @@ static double find_max_delta(
        eps *= fac;
        stable = TRUE;
    }
    fac = 0.5;
    fac = 0.5f;

    if ( stable )
    {
@@ -440,16 +311,16 @@ static double find_max_delta(

static void recover_samples(
    const int16_t bfi_count,
    const float *outbuf,
    float *outbuf,
    float *rec_frame )
{
    int16_t i;
    float zeroes[LFE_PLC_RECLEN];
    double delta, fac, att;
    double d_outbuf[LFE_PLC_BUFLEN], d_r[LFE_PLC_LPCORD + 1], d_a[LFE_PLC_LPCORD + 1], d_pee[LFE_PLC_LPCORD + 1];
    float delta, fac, att;
    float d_outbuf[LFE_PLC_BUFLEN], d_r[LFE_PLC_LPCORD + 1], d_a[LFE_PLC_LPCORD + 1] = {0.f}, d_pee[LFE_PLC_LPCORD + 1] = {0.f};

    mvr2d( outbuf, d_outbuf, LFE_PLC_BUFLEN );
    d_autocorr( d_outbuf, d_r, LFE_PLC_LPCORD, LFE_PLC_BUFLEN, d_hamm_lfe_plc, 0, 1, 1 );
    mvr2r( outbuf, d_outbuf, LFE_PLC_BUFLEN );
    autocorr( d_outbuf, d_r, LFE_PLC_LPCORD, LFE_PLC_BUFLEN, d_hamm_lfe_plc, 0, 1, 1 );

    if ( d_r[0] < POW_THR * LFE_PLC_BUFLEN )
    {
@@ -460,8 +331,8 @@ static void recover_samples(

    delta = find_max_delta( d_a + 1 );

    fac = 1.0 + delta;
    att = 1.0;
    fac = 1.0f + delta;
    att = 1.0f;

    if ( bfi_count >= LFE_PLC_MUTE_THR )
    {
@@ -472,11 +343,11 @@ static void recover_samples(
    for ( i = 1; i <= LFE_PLC_LPCORD; i++ )
    {
        d_a[i] = d_a[i] * fac;
        fac *= att * ( 1.0 + delta );
        fac *= att * ( 1.0f + delta );
    }

    set_zero( zeroes, LFE_PLC_RECLEN );
    d_syn_filt( d_a, LFE_PLC_LPCORD, zeroes, rec_frame, LFE_PLC_RECLEN, outbuf + LFE_PLC_BUFLEN - LFE_PLC_LPCORD );
    syn_filt( d_a, LFE_PLC_LPCORD, zeroes, rec_frame, LFE_PLC_RECLEN, outbuf + LFE_PLC_BUFLEN - LFE_PLC_LPCORD, 0 );

    return;
}
@@ -490,7 +361,7 @@ static void recover_samples(

void ivas_lfe_tdplc(
    LFE_DEC_HANDLE hLFE,       /* i/o: LFE decoder handle           */
    const float *prevsynth,    /* i  : previous frame synthesis     */
    float *prevsynth,    /* i  : previous frame synthesis     */
    float *ytda,               /* o  : output time-domain buffer    */
    const int16_t output_frame /* i  : output frame length          */
)