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

Fix for EVS JBM streams bitexactness issue

parent ac9660db
Loading
Loading
Loading
Loading
Loading
+206 −0
Original line number Diff line number Diff line
@@ -1078,6 +1078,211 @@ UWord8 apa_exec_fx(
        return 3;
    }

    /* get target length */
    test();
    test();
    IF( EQ_16( ps->l_frm, 480 ) || EQ_16( ps->l_frm, 960 ) || EQ_16( ps->l_frm, 1920 ) )
    {
        /* decomposite ps->l_frm into 15<<i, e.g. 480=15<<5 */
        i = sub( 15 - 4, norm_s( ps->l_frm ) );
        /* this only works for 20ms framing */
        assert( ps->l_frm == shl( shr( ps->l_frm, i ), i ) );
        // assert( i_mult2( sub( ps->scale, 100 ), add( ps->nFramesSinceSetScale, 1 ) ) == ( ps->scale - 100 ) * ( ps->nFramesSinceSetScale + 1 ) );
        expScaling = L_shr_r( L_mult0( i_mult2( sub( ps->scale, 100 ), add( (Word16) ps->nFramesSinceSetScale, 1 ) ), 19661 /*15*(1<<2)/100.0 Q15*/ ), sub( 15 + 2, i ) );
    }
    ELSE
    {
        /* decomposite ps->l_frm into 5<<i, e.g. 320=5<<6 */
        i = sub( 15 - 3, norm_s( ps->l_frm ) );
        /* this only works for 20ms framing */
        assert( ps->l_frm == shl( shr( ps->l_frm, i ), i ) );
        // assert( i_mult2( sub( ps->scale, 100 ), add( ps->nFramesSinceSetScale, 1 ) ) == ( ps->scale - 100 ) * ( ps->nFramesSinceSetScale + 1 ) );
        expScaling = L_shr_r( L_mult0( i_mult2( sub( ps->scale, 100 ), add( (Word16) ps->nFramesSinceSetScale, 1 ) ), 13107 /*5*(1<<3)/100.0 Q15*/ ), sub( 15 + 3, i ) );
    }
    actScaling = L_sub( ps->diffSinceSetScale, ps->l_frm );
    l_frm_out_target = L_sub( expScaling, actScaling );

    /* Wait until we have l_frm outputs samples */
    /* (required to search for correlation in the past). */
    /* If we don't have enough samples, simply copy input to output */
    IF( LT_32( ps->l_buf_out, ps->l_frm ) )
    {
        FOR( i = 0; i < ps->l_frm; i++ )
        {
            a_out[i] = a_in[i];
            move16();
        }
        l_frm_out = ps->l_frm;
        move16();
    }
    ELSE
    {
        Word16 *buf_out_ptr = &( ps->buf_out_fx[ps->l_buf_out - ps->l_frm] );
        Word16 *frm_in_ptr = &( frm_in[ps->l_frm] );

        /* fill input frame */
        /* 1st input frame: previous output samples */
        FOR( i = 0; i < ps->l_frm; i++ )
        {
            frm_in[i] = buf_out_ptr[i];
            move16();
        }
        /* 2nd input frame: new input samples */
        FOR( i = 0; i < ps->l_frm; i++ )
        {
            frm_in_ptr[i] = a_in[i];
            move16();
        }
        /* no scaling */
        IF( EQ_32( ps->scale, 100 ) )
        {
            copy_frm_fx( ps, frm_in, a_out, &l_frm_out );
        }
        /* shrink */
        ELSE IF( LT_32( ps->scale, 100 ) )
        {
            shrink_frm_fx( ps, frm_in, maxScaling, a_out, &l_frm_out );
        }
        /* extend */
        ELSE
        {
            extend_frm_fx( ps, frm_in, a_out, &l_frm_out );
        }
        /* control the amount/frequency of scaling */
        IF( NE_32( l_frm_out, ps->l_frm ) )
        {
            test();
            IF( NE_32( maxScaling, 0 ) &&
                GT_32( abs_s( extract_l( L_sub( ps->l_frm, l_frm_out ) ) ), maxScaling ) )
            {
                /* maxScaling exceeded -> discard scaled frame */
                copy_frm_fx( ps, frm_in, a_out, &l_frm_out );
            }
            ELSE IF( GT_32( L_abs( l_frm_out_target ), ps->l_frm ) ) /* ignore small difference */
            {
                dl_copied = L_sub( l_frm_out_target, ps->l_frm );
                dl_scaled = L_sub( l_frm_out_target, l_frm_out );
                /* discard scaled frame if copied frame is closer to target length */
                IF( LT_32( L_abs( dl_copied ), L_abs( dl_scaled ) ) )
                {
                    copy_frm_fx( ps, frm_in, a_out, &l_frm_out );
                }
            }
        }
    }

    /* copy output to internal buffer */
    /* avoid buffer overflow: */
    /* discard old samples; always keep at least most recent l_frm samples */
    IF( GT_32( L_add( ps->l_buf_out, l_frm_out ), ps->buf_out_capacity ) )
    {
        Word16 *buf_out_ptr1 = ps->buf_out_fx;
        Word16 *buf_out_ptr2;

        l_rem = extract_l( L_sub( ps->l_frm, l_frm_out ) );
        if ( l_rem < 0 )
        {
            l_rem = 0;
            move16();
        }
        buf_out_ptr2 = &( ps->buf_out_fx[ps->l_buf_out - l_rem] );
        FOR( i = 0; i < l_rem; i++ )
        {
            buf_out_ptr1[i] = buf_out_ptr2[i];
            move16();
        }
        ps->l_buf_out = l_rem;
        move16();
    }
    /* append new output samples */
    IF( GT_32( L_add( ps->l_buf_out, l_frm_out ), ps->buf_out_capacity ) )
    {
        return 5;
    }
    {
        Word16 *buf_out_ptr = &( ps->buf_out_fx[ps->l_buf_out] );
        FOR( i = 0; i < l_frm_out; i++ )
        {
            buf_out_ptr[i] = a_out[i];
            move16();
        }
    }
    ps->l_buf_out = (UWord16) L_add( ps->l_buf_out, l_frm_out );
    move16();

    *l_out = l_frm_out;
    move16();
    /* update time */
    ps->l_in_total = UL_addNsD( ps->l_in_total, ps->l_frm );
    move32();

    test();
    IF( LT_32( L_abs( ps->diffSinceSetScale ), L_sub( 0x7FFFFF, L_sub( l_frm_out, ps->l_frm ) ) ) &&
        LT_64( ps->nFramesSinceSetScale, statsResetThreshold ) )
    {
        ps->diffSinceSetScale = L_add( ps->diffSinceSetScale, L_sub( l_frm_out, ps->l_frm ) );
        move32();
        ps->nFramesSinceSetScale = UL_addNsD( ps->nFramesSinceSetScale, 1 );
        move32();
    }
    ELSE /* scale statistics down to avoid overflow */
    {
        ps->diffSinceSetScale = L_shr( ps->diffSinceSetScale, (Word16) statsResetShift );
        move32();
        ps->nFramesSinceSetScale = UL_lshr( ps->nFramesSinceSetScale, (Word16) statsResetShift );
        move32();
    }

    return 0;
}

UWord8 apa_exec_ivas_fx(
    apa_state_t *ps,     /* i/o: state struct                                  */
    const Word16 a_in[], /* i  : input samples                                 */
    UWord16 l_in,        /* i  : number of input samples                       */
    UWord16 maxScaling,  /* i  : allowed number of inserted/removed samples    */
    Word16 a_out[],      /* o  : output samples                                */
    UWord16 *l_out       /* o  : number of output samples                      */
)
{
    UWord16 i;
    Word16 frm_in[APA_BUF]; /* TODO(mcjbm): this buffer could be smaller - always allocates space for 16 channels */
    UWord16 l_frm_out;
    Word16 l_rem;
    Word32 dl_scaled, dl_copied, l_frm_out_target;
    Word32 expScaling, actScaling;
    UWord32 statsResetThreshold, statsResetShift;

    statsResetThreshold = 1637;
    move32();
    statsResetShift = 2;
    move32();

    /* Convert max_scaling from "per channel" to total */
    maxScaling = (UWord16) imult3216( maxScaling, ps->num_channels );

    /* make sure no invalid output is used */
    *l_out = 0;
    move16();
    l_frm_out = 0;
    move16();

    /* make sure pointer is valid */
    IF( ps == NULL )
    {
        return 1;
    }
    /* check available rate */
    IF( ps->rate == 0 )
    {
        return 2;
    }
    /* check size of input */
    IF( NE_32( l_in, ps->l_frm ) )
    {
        return 3;
    }

    /* get target length */
    test();
    test();
@@ -1231,6 +1436,7 @@ UWord8 apa_exec_fx(

    return 0;
}

#else
uint8_t apa_exec(
    apa_state_t *ps,     /* i/o: state struct                                  */
+1 −0
Original line number Diff line number Diff line
@@ -145,6 +145,7 @@ bool apa_set_quality( apa_state_t *s, float quality, uint16_t qualityred, uint16
bool apa_exit( apa_state_t **s );

uint8_t apa_exec( apa_state_t *s, const float a_in[], uint16_t l_in, uint16_t maxScaling, float a_out[], uint16_t *l_out );
uint8_t apa_exec_ivas_fx( apa_state_t *s, const Word16 a_in[], uint16_t l_in, uint16_t maxScaling, Word16 a_out[], uint16_t *l_out );
uint8_t apa_exec_fx( apa_state_t *s, const Word16 a_in[], uint16_t l_in, uint16_t maxScaling, Word16 a_out[], uint16_t *l_out );

#endif /* JBM_PCMDSP_APA_H */
+26 −10
Original line number Diff line number Diff line
@@ -1088,21 +1088,37 @@ ivas_error IVAS_DEC_GetSamples(

            // tmp apaExecBuffer
            Word16 tmp_apaExecBuffer[APA_BUF];

            IF( EQ_16( (Word16) hIvasDec->mode, IVAS_DEC_MODE_EVS ) )
            {
                for ( int i = 0; i < APA_BUF_PER_CHANNEL * nTransportChannels; ++i )
                {
                tmp_apaExecBuffer[i] = extract_l( L_shr( hIvasDec->apaExecBuffer_fx[i], Q12 ) );
                    tmp_apaExecBuffer[i] = extract_l( L_shr( hIvasDec->apaExecBuffer_fx[i], Q11 ) );
                }
                IF( apa_exec_fx( hIvasDec->hTimeScaler, tmp_apaExecBuffer, (UWord16) imult3216( hIvasDec->nSamplesFrame, nTransportChannels ), (UWord16) hIvasDec->tsm_max_scaling, tmp_apaExecBuffer, &nTimeScalerOutSamples ) != 0 )
                {
                    return IVAS_ERR_UNKNOWN;
                }
                for ( int i = 0; i < APA_BUF_PER_CHANNEL * nTransportChannels; ++i )
                {
                    hIvasDec->apaExecBuffer_fx[i] = L_shl( tmp_apaExecBuffer[i], Q11 );
                }
            }
            ELSE
            {
                for ( int i = 0; i < APA_BUF_PER_CHANNEL * nTransportChannels; ++i )
                {
                    tmp_apaExecBuffer[i] = extract_l( L_shr( hIvasDec->apaExecBuffer_fx[i], Q12 ) );
                }
                IF( apa_exec_ivas_fx( hIvasDec->hTimeScaler, tmp_apaExecBuffer, (UWord16) imult3216( hIvasDec->nSamplesFrame, nTransportChannels ), (UWord16) hIvasDec->tsm_max_scaling, tmp_apaExecBuffer, &nTimeScalerOutSamples ) != 0 )
                {
                    return IVAS_ERR_UNKNOWN;
                }

                for ( int i = 0; i < APA_BUF_PER_CHANNEL * nTransportChannels; ++i )
                {
                    hIvasDec->apaExecBuffer_fx[i] = L_shl( tmp_apaExecBuffer[i], Q12 );
                }

            }
            assert( LE_32( (Word32) nTimeScalerOutSamples, APA_BUF ) );
            nSamplesTcsScaled = idiv1616( extract_l( nTimeScalerOutSamples ), nTransportChannels );
        }