dtmfr.c
来自「Express DSP compliant C55x DTMF detector」· C语言 代码 · 共 194 行
C
194 行
/*-------------------------------------------------------------------------*
* *
* THIS IS AN UNPUBLISHED WORK CONTAINING CONFIDENTIAL AND PROPRIETARY *
* INFORMATION. IF PUBLICATION OCCURS, THE FOLLOWING NOTICE APPLIES: *
* "COPYRIGHT 2001 MIKET DSP SOLUTIONS, ALL RIGHTS RESERVED" *
* *
*-------------------------------------------------------------------------*/
#include "dtmfi.h"
/*--------------------- local defs ----------------------------------------*/
/*--------------------- public vars ---------------------------------------*/
#if ! defined(_dsp)
#if (IDTMF_FR_SZ == 40)
S16 DBG_sFrameEn;
S32 DBG_slDialEn;
#endif
#include <stdlib.h>
#endif
/*--------------------- local vars ----------------------------------------*/
/*--------------------- local functions -----------------------------------*/
/*--------------------- public functions ---------------------------------*/
/*-------------------------------------------------------------------------*/
static void _test
/*-------------------------------------------------------------------------*/
(
DTMF_tDb *pDb,
DTMF_tSc *pSc
)
{
const IDTMF_tCfg *pCfg = pDb->pCfg;
S16 sTestFailed = 0;
/* test that frame energy is high enough. */
if (pSc->sSumEn < pCfg->sMinEnThr)
sTestFailed |= DTMF_MASK_MIN_EN;
#if (IDTMF_FR_SZ == 40)
#if ! defined(_dsp)
DBG_sFrameEn = pDb->v.sZFrameEn;
#endif
/* test that {dial + lo + hi} energies constitute
a major part of average of 2 frames energy. */
if ((pDb->v.sZFrameEn - pSc->sSumDialEn) > pCfg->sSumEnThr)
sTestFailed |= DTMF_MASK_SUM_EN;
#else
if ((pSc->sFrameEn - pSc->sSumDialEn) > pCfg->sSumEnThr)
sTestFailed |= DTMF_MASK_SUM_EN;
#endif
/* test leading edge */
{
#if (IDTMF_FR_SZ == 40)
S16 ac0 = pDb->v.asSumEn[0];
S16 ac1 = pDb->v.asSumEn[1];
S16 ac2 = pDb->v.asSumEn[4];
S16 ac3 = pDb->v.asSumEn[5];
if (ac0 > ac1) ac0 = ac1; /* ac0 = min of 2 most recent frames */
if (ac2 < ac3) ac2 = ac3; /* ac2 = max of 2 oldest frames */
ac0 -= ac2; /* energy diff */
#else
S16 ac0 = pDb->v.asSumEn[0];
S16 ac1 = pDb->v.asSumEn[2];
ac0 -= ac1;
#endif
if (ac0 < pCfg->sNoiseThr)
sTestFailed |= DTMF_MASK_RS_EDGE;
}
/* test falling edge */
if ((pDb->v.Stat.sEn - pSc->sSumEn) < pCfg->sNoiseThr)
sTestFailed |= DTMF_MASK_FL_EDGE;
/* test that lo(idx) and hi(idx) energies are reasonably stable */
if (abs(pSc->sLoMaxFreqEn - pDb->v.Stat.sLoEn) > pCfg->sVarThr)
sTestFailed |= DTMF_MASK_STABLE;
if (abs(pSc->sHiMaxFreqEn - pDb->v.Stat.sHiEn) > pCfg->sVarThr)
sTestFailed |= DTMF_MASK_STABLE;
/* test that <2k energy is significantly bigger than >2k energy */
if (pSc->s2kEnDlt < pCfg->s2kUpThr)
sTestFailed |= DTMF_MASK_2K_BOUND;
/* test that twists are ok */
/* if ((pSc->Hi.sMaxFreqEn - pSc->Lo.sMaxFreqEn) > pCfg->sFwdTwistThr) */
if ((pSc->sHiBpEn-pSc->sLoBpEn) > (pCfg->sFwdTwistThr+(170+85)))
sTestFailed |= DTMF_MASK_FWD_TWIST;
if ((pSc->sHiBpEn-pSc->sLoBpEn) < -(pCfg->sRevTwistThr-85) )
sTestFailed |= DTMF_MASK_REV_TWIST;
if (pDb->v.sState < DTMF_ST_TONE)
{
/* DFT delay lines are not full. at least one frame less.
we shall account for wider sinc mainlobe and lower energy.
Noise does not have much influence on the parameters
in this case, so the threshold are hard coded.
tuning criteria was chosen the number of early-on hits
on talk-off imunity test.
varying those thrs shall affect early detection delay
and talk-off immunity as well.
*/
if ((pSc->sLoBpEn - pSc->sLoMaxFreqEn) > (6*IDTMF_1DB))
sTestFailed |= DTMF_MASK_LO_PART;
if ((pSc->sLoMaxFreqEn - pSc->sLoNextEn) < (5*IDTMF_1DB))
sTestFailed |= DTMF_MASK_LO_CLEAN;
#if (IDTMF_FR_SZ == 40)
if ((pSc->sHiBpEn - pSc->sHiMaxFreqEn) > (4*IDTMF_1DB))
sTestFailed |= DTMF_MASK_HI_PART;
if ((pSc->sHiMaxFreqEn - pSc->sHiNextEn) < (7*IDTMF_1DB))
sTestFailed |= DTMF_MASK_HI_CLEAN;
#endif
}
else
{
if ((pSc->sLoBpEn - pSc->sLoMaxFreqEn) > pCfg->sPartThr)
sTestFailed |= DTMF_MASK_LO_PART;
if ((pSc->sLoMaxFreqEn - pSc->sLoNextEn) < pCfg->sCleanThr)
sTestFailed |= DTMF_MASK_LO_CLEAN;
#if (IDTMF_FR_SZ == 40)
if ((pSc->sHiBpEn - pSc->sHiMaxFreqEn) > pCfg->sPartThr)
sTestFailed |= DTMF_MASK_HI_PART;
if ((pSc->sHiMaxFreqEn - pSc->sHiNextEn) < pCfg->sCleanThr)
sTestFailed |= DTMF_MASK_HI_CLEAN;
#endif
}
#if (IDTMF_FR_SZ == 80)
if ((pSc->sHiBpEn - pSc->sHiMaxFreqEn) > pCfg->sPartThr)
sTestFailed |= DTMF_MASK_HI_PART;
if ((pSc->sHiMaxFreqEn - pSc->sHiNextEn) < pCfg->sCleanThr)
sTestFailed |= DTMF_MASK_HI_CLEAN;
#endif
if (abs(pSc->sLoFreqDev) > pCfg->sMaxFreqDevThr)
sTestFailed |= DTMF_MASK_LO_INRANGE;
if (abs(pSc->sHiFreqDev) > pCfg->sMaxFreqDevThr)
sTestFailed |= DTMF_MASK_HI_INRANGE;
pSc->sDigit = pSc->sLoFreqNo | (pSc->sHiFreqNo<<2);
if (pDb->v.sLastDigit != pSc->sDigit)
sTestFailed |= DTMF_MASK_SAME_FRQ;
pSc->sTestFailed = sTestFailed;
}
/*-------------------------------------------------------------------------*/
void dtmf_filter_test
/*-------------------------------------------------------------------------*/
(
DTMF_tDb *pDb,
DTMF_tSc *pSc,
S16 *psIn
)
{
dtmf_move_data_in (pDb, pSc, psIn);
dtmf_2k_filter (pDb, pSc);
dtmf_lo_filter (pDb, pSc);
dtmf_hi_filter (pDb, pSc);
pSc->sSumEn = dtmf_en2log(pSc->slLoBpEn + pSc->slHiBpEn);
pDb->v.asSumEn[0] = pSc->sSumEn;
dtmf_dial_filter (pDb, pSc);
dtmf_lo_dft_main (pDb, pSc);
dtmf_lo_sort (pDb, pSc);
dtmf_lo_dft_dev (pDb, pSc);
dtmf_lo_freq (pDb, pSc);
dtmf_hi_dft_main (pDb, pSc);
dtmf_hi_sort (pDb, pSc);
dtmf_hi_dft_dev (pDb, pSc);
dtmf_hi_freq (pDb, pSc);
dtmf_frame_en (pDb, pSc);
_test(pDb, pSc);
dtmf_move_data_out (pDb, pSc);
}
/*-------------------------------------------------------------------------*/
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?