⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lecas.cpp

📁 The line echo canceller (LEC) is designed to provide the maximum attainable transparent voice qualit
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    if (Tmp < -32768) Tmp = -32768;
    pSc->asNormErr[base] = (S16)Tmp;
/* ADAPT */
    pData = pDb->psTxF + LEC_FLT2_SZ + base;
    psFlt = pDb->asAdf2;
    /* Frame 0, pm = 1 */

    slNormErr = ((S32)pSc->asNormErr[base]);

    for (Tap = 0; Tap < ILEC_FR_SZ; Tap += 1)
    {
	    S32 Sum = (((S32)*psFlt) << 15) + 0x4000L;
	        Sum += (slNormErr * *pData--)<<4;

    /*    *pFilter += (S16)(Sum/ 0x8000L);  correct coeff */

        *psFlt++ = (S16)(Sum >> 15);
    }
    for (k = 0; k < 4; k++)
    {
        for (Tap = 0; Tap < ILEC_FR_SZ/2; Tap += 1)
        {
	        S32 Sum = (((S32)*psFlt) << 15) + 0x4000L; 
    	        Sum += (slNormErr * *pData--)<<(6-k);

        /*    *pFilter += (S16)(Sum/ 0x8000L);  correct coeff */

            *psFlt++ = (S16)(Sum >> 15);
        }
    }
}
/*-------------------------------------------------------------------------*/
void                        lec_adapt_slow_high
/*-------------------------------------------------------------------------*/
(
LEC_tDb *pDb,
LEC_tSc *pSc,
S16 base,
S16 SSS
)
{
	S16 *psData;
	S16 *psFlt;
	S16 Tap;
	S16 k;
	S32 slAcc;

/* NORMALIZE ERROR */
    for (k = 0; k < LEC_SECTION_SZ; k++)
    {
	    slAcc = ((pSc->asErr2[k+base] * (long)SSS + 0x8) >> 4);
        if (slAcc > 32767) slAcc = 32767;
        if (slAcc < -32768) slAcc = -32768;
	    pSc->asNormErr[k+base] = (S16)slAcc;
    }

/* ADAPT */

    psData = pDb->psTxF + LEC_FLT2_SZ + base;
    psFlt = pDb->asAdf2;

    for (Tap = 0; Tap < LEC_FLT2_SZ; Tap += 1)
    {
        S32 slB = 0;
	    slAcc = ((long)*psFlt << 15) + 0x4000L;
	    for (k = 0; k < LEC_SECTION_SZ; k++)
	    {
		    slB += (S32)(pSc->asNormErr[k+base]) * *psData++;
	    }
        slAcc += slB>>2;
        /*    *pFilter += (S16)(Sum/ 0x8000L);  correct coeff */

	    *psFlt++ = (S16)(slAcc >> 15);
        psData   -= LEC_SECTION_SZ + 1; /* next back */
    }
}
/*-------------------------------------------------------------------------*/
void                        lec_adapt_slow_low
/*-------------------------------------------------------------------------*/
(
LEC_tDb *pDb,
LEC_tSc *pSc,
S16 base,
S16 SSS
)
{
	S16 *psData;
	S16 *psFlt;
	S16 Tap;
	S16 k;
	S32 slAcc;


    for (k = 0; k < LEC_SECTION_SZ; k++)
    {
	    slAcc = pSc->asErr2[k+base] * (long)SSS;
        if (slAcc > 32767) slAcc = 32767;
        if (slAcc < -32768) slAcc = -32768;
	    pSc->asNormErr[k+base] = (S16)slAcc;
    }

    psData = pDb->psTxF + LEC_FLT2_SZ + base;
    psFlt = pDb->asAdf2;

    for (Tap = 0; Tap < LEC_FLT2_SZ; Tap += 1)
    {
        S32 slB = 0;
	    slAcc = ((long)*psFlt << 15) + 0x4000L;
	    for (k = 0; k < LEC_SECTION_SZ; k++)
	    {
		    slB += (S32)(pSc->asNormErr[k+base]) * *psData++;
	    }
        slAcc += slB << (6-2);

        /*    *pFilter += (S16)(Sum/ 0x8000L);  correct coeff */

	    *psFlt++ = (S16)(slAcc >> 15);
        psData   -= LEC_SECTION_SZ + 1; /* next back */
    }
}

/*-------------------------------------------------------------------------*/
void                         lec_shift_err2
/*-------------------------------------------------------------------------*/
(
LEC_tDb *pDb,
LEC_tSc *pSc
)
{
	S16 sShift = pDb->Adf2.sShift;
	
    if (sShift) {
    	S16 k;
	    for (k = 0; k < ILEC_FR_SZ; k++)
    	{
    		S32 acc = pSc->asErr2[k];
    		acc += (1<<(sShift-1));
    		acc >>= sShift; 
        	pSc->asErr2[k] = (S16)acc;
        }
    }
}

/*-------------------------------------------------------------------------*/
S16                         lec_step_size_corr_slow
/*-------------------------------------------------------------------------*/
(
LEC_tDb *pDb,
LEC_tSc *pSc,
S16 sBase
)
{
    /* current error averaging */
    S32 ac0 = 0;
    S16 sEn;
    S16 sErleLoss;
    S16 k;

    for (k = 0; k < LEC_SECTION_SZ; k++)
    {
        ac0 += pSc->asErr2[sBase+k] * (S32) pSc->asErr2[sBase+k];
    }
    ac0 /= LEC_SECTION_SZ;
    ac0 >>= pDb->Adf2.sShift*2;

    sEn = lec_en2log(ac0) + 512*(5-2)+125;

    /* fast up, slow down */
    if (sEn > pDb->sErrAvrEn)
    {
        pDb->sErrAvrEn += (sEn - pDb->sErrAvrEn + 1) >> 1;
    }
    else
    {
        pDb->sErrAvrEn += (sEn - pDb->sErrAvrEn + 4) >> 3;
    }

    sErleLoss = pDb->sErrAvrEn - pSc->sExpectedErrorEn;

    if (pSc->sExpectedErrorEn < pDb->VadErr.sEnNoise)
    {
        if (pSc->sExpectedErrorEn > (pDb->VadErr.sEnNoise - LEC_DB(6)))
        {
            /// within allowed range
            sErleLoss -= (pDb->VadErr.sEnNoise - pSc->sExpectedErrorEn);
        }
        else
        {
            /// lower than allowed range
            sErleLoss -= LEC_DB(6);
        }
    }
    else ; // that's pure loss

    if (sErleLoss < 0) 
        sErleLoss = 0;

    /* we need to take squared coeff */
    return lec_exp(-sErleLoss);

}

/*-------------------------------------------------------------------------*/
S16                         lec_step_size_corr_fast
/*-------------------------------------------------------------------------*/
(
LEC_tDb *pDb,
LEC_tSc *pSc,
S16 sBase
)
{
    /* current error averaging */
    S32 ac0 = 0;
    S16 sEn;
    S16 sErleLoss;

    ac0 = pSc->asErr2[sBase] * (S32) pSc->asErr2[sBase];
    ac0 >>= pDb->Adf2.sShift*2;

    sEn = lec_en2log(ac0) + 512*(5-2)+125;

    /* fast up, slow down */
    if (sEn > pDb->sErrAvrEn)
    {
        pDb->sErrAvrEn += (sEn - pDb->sErrAvrEn + 4) >> 3;
    }
    else
    {
        pDb->sErrAvrEn += (sEn - pDb->sErrAvrEn + 16) >> 5;
    }

    sErleLoss = pDb->sErrAvrEn - pSc->sExpectedErrorEn;

    if (sErleLoss < 0) 
        sErleLoss = 0;

    /* we need to take squared coeff */
    return lec_exp(-sErleLoss);

}

/*-------------------------------------------------------------------------*/
S16                         lec_step_size_corr_fast2
/*-------------------------------------------------------------------------*/
(
LEC_tDb *pDb,
LEC_tSc *pSc,
S16 sBase
)
{
    /* current error averaging */
    S32 ac0 = 0;
    S16 sEn;
    S16 sErleLoss;
    S16 sCorr;

    ac0 = pSc->asErr2[sBase] * (S32) pSc->asErr2[sBase];
//    ac0 >>= pDb->Adf2.sShift*2;

    sEn = lec_en2log(ac0)+512*(5-2)+125;

    /* fast up, slow down */
    if (sEn > pDb->sErrAvrEn)
    {
        pDb->sErrAvrEn += (sEn - pDb->sErrAvrEn + 4) >> 3;
    }
    else
    {
        pDb->sErrAvrEn += (sEn - pDb->sErrAvrEn + 16) >> 5;
    }

    sErleLoss = pDb->sErrAvrEn - pSc->sExpectedErrorEn;

    if (sErleLoss < 0) 
        sErleLoss = 0;

    /* we need to take squared coeff */
    {
    	S16 log = -sErleLoss;
    	S32 a = log<<2;
    	S16 t = log>>10;
    	S16 x = 4096 + (S16)(a&4095);
    	if (t > 0) sCorr = x<<t; else sCorr = x>>(-t);
    }
	return sCorr;
}

/*-------------------------------------------------------------------------*/
void                        lec_adapt_fast
/*-------------------------------------------------------------------------*/
(
LEC_tDb *pDb,
LEC_tSc *pSc
)
{
    S16 base;
    U16 uEn;

    pSc->slEn = lec_get_xz(pDb->psHst + LEC_FLT2_SZ, 
                           pDb->psTxF + LEC_FLT2_SZ);
                           
    for (base = 0; base < ILEC_FR_SZ; base++)
    {
    	S32 slEn;
        S16 SSS; /* corrected step size */

/* CANCEL ECHO */
        pSc->asErr2[base] = lec_cancel(
             pDb->psHst + LEC_FLT2_SZ + base,
             pDb->asAdf2,
             pSc->psRx[base]
             ); 
		        
        if (base != 0)
        {
            pSc->slEn = lec_update_xz(pSc->slEn,
                     				pDb->psHst + LEC_FLT2_SZ + base,
            		                pDb->psTxF + LEC_FLT2_SZ + base 
                                 	);
        }
        
        slEn = pSc->slEn + pDb->Adf2.slAcc;
		uEn = lec_step_size(slEn, &pSc->sStepSize);
        pSc->uAdaptMode |= uEn<<2;

        /* compute energy and step size */
/* ADJUST STEP SIZE */
        pSc->sStepCorr = lec_step_size_corr_fast2(pDb, pSc, base);
        SSS = (S16)((pSc->sStepSize * (S32) pSc->sStepCorr + (1<<11))>>12);

        switch(uEn) {
        case 1:
        	lec_adapt_fast_high(pDb, pSc, base, SSS);
        	break;
        case 2:
        	lec_adapt_fast_low(pDb, pSc, base, SSS);
            break;
        default:
            break;
        }
    } /* end of for: ILEC_FR_SZ */
}  




⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -